From 1b1cb0c54036f4db89efe5a7dcf5255b17853bd0 Mon Sep 17 00:00:00 2001 From: cbbcbail Date: Thu, 1 Aug 2024 17:19:45 -0600 Subject: [PATCH] Minor class reorganization. --- data/Fig1-designProcess/blend1Subset.pickle | Bin 2574 -> 2574 bytes data/Fig1-designProcess/distinctSubset.pickle | Bin 2094 -> 2094 bytes data/Fig1-designProcess/fullData.pickle | Bin 3782 -> 3782 bytes data/Fig1-designProcess/hullSubset.pickle | Bin 888 -> 936 bytes data/Fig1-designProcess/outliersSubset.pickle | Bin 1614 -> 1614 bytes data/solverLog.csv | 4 + figures/Fig1-designProcess/express.pdf | Bin 16862 -> 16895 bytes flexibleSubsetSelection/__init__.py | 1 + flexibleSubsetSelection/color.py | 73 +++++++++++++++ flexibleSubsetSelection/loss.py | 6 +- flexibleSubsetSelection/plot.py | 83 ++---------------- flexibleSubsetSelection/sets.py | 9 +- flexibleSubsetSelection/solver.py | 14 ++- jupyter/Fig1-designProcess.ipynb | 12 ++- jupyter/Fig2&3-objectives.ipynb | 2 +- jupyter/Fig4-performance.ipynb | 2 +- jupyter/Fig5-scatterplotOverdraw.ipynb | 2 +- 17 files changed, 108 insertions(+), 100 deletions(-) create mode 100644 flexibleSubsetSelection/color.py diff --git a/data/Fig1-designProcess/blend1Subset.pickle b/data/Fig1-designProcess/blend1Subset.pickle index ca683e35037bb020a976cda9634c7d89dc1205e7..7fdb1ba0ee10486c6229f5963b6a646dfc88017a 100644 GIT binary patch delta 1822 zcmXZZdo+}J7{Kutvor57#>~8CnjsB}HhZE*7ad#gBi)&b$|ZI+NYRZ}S(h5SwWukQ ztO--BuA&Qyw(?G66CIK!DpI5<E0Jg=(-P{uK zjtr?WWz`&cEhkl&*QdG;0mSKhJyQe{;GnbA&Z@M4+}?ze0A~VDmu$YD@5O;zucA&^ zXYxQBI_f`v&lolH@royR?5D!^d!i7ptMYDb?Xf0JEpP8kjs@B*x}m|&4%@yP3ofx7DIy4qh~zN2<@B%YwP z89`9|V@2KC4$|k@d6T0w9NfEtK1J)ZfcWp?z=zC_q&xNJ{9PUlIFmmTbz9EB;FtQa zz>j=Pt&|olZ;By+=y3~s>t_Nx^pZk(o=m8nt4d{cTSBq##>xc>3)r<>{e#BX5N0Qq zKAOFU4`!^DCdEtmu%8v5&8cI9-_32|jF-LSkhrSQWEBUr%I2usQVgVVtb@fjaHyLX zw8*%NALyy>NsiGdMQ$@)_{S zyF$>hMgVkKr?=qS-O31A*pd@^U|UcoRvhEOLS2l^UM2u+PpjjLP%}7FO3A?($PGY{Y7z&)qE5lY+$Si}c;gzz8(9@@B7cxwmA-FWrGS-!8y=`s6l%!}Bt z?2uHaaOFXqIQ`tw3H;j}57!Uk@OXBCVQ01_Xw-?dN#)gK zuvzNU0|5hMPHcq>Jx>IC_L~E0l%q0Y%qr0R8bv`G3%Qn=vrx*iY_@eo@-?=cNa(6Jg zPlIW7Ig9Tq2-q<|PmmM}piz~2vN4t&q?i8SRIY(>`;lV_! zPvA3UKb5Lq>2)$}GK?wn&Ru#V2F(N4-Ho?+a4g&Pe)m&M4!y_m;7bY-Y~MP5#bfx} zuZM{P1B?48DZC2Et}%u6i>vWS?Eu;R)o-0Fng@&cqZu}<*l^M|+{e@DHE9%kS)1NV zQ^!wtRJt%9QMBNj8q4Y;YNmbhK5i);9{So;#h$uNRm9W`iH`P>abriUJRdP&mv0kG zafitRWpMxA06tM{MQ7;A4Y2QnBbi7;q!H2>X@cY+xkwSx3~7!OBdw5Aku$z4!R*jt zCej``8!17~LC#I9XNW@=p>jbkMXo}+A*DzUq&LzB>5KG3%8`IBy!Bl>>^555 QL6##ameobBwT@AlLQOSoub1!h&-?j&{(W9gIzOFXX-p+lbL>8aDw%MK zc3J-(oe9MJT|r3&EXdjOZ6dIh3!9w0H?|AZVUx|r5UF| zlfzxrSE$1r0=g;^LJntqCON4>n|I8a5cYH+rr6d9EF7ctIt(>H)VIrGuA3ShZ^-QQ z;Rqonqi2SE`$Lo%w<4~ma00RGc#Y{5InJ8^ui6K@zX@{+^6{5W8r zYP;ca$b0hl;xqE*`IBf()$EOCrc7YZwU2t;!vlr$E@D{`A9B;y4?^c-YCciw?A`_>jxhrKt#=7pThGq6^M7fpk< zyX!3UJO@#Ew8Pl$=rIMuk4nmlX*zI!F^=^%1uyuvojC)b`?nOUWRIH?9ut zfjb#OV5r{9JO^$`XQDv!CK z=N3HSsH9=QKNkxLiYcTP}XiSyEw{SqarPx-rQg(@2cet5_#4$+}D z`4r#DM~OBOLnBWuC*{a|g>LXZ4ij931v>H!ItZ)8mkV6WNO_0fncI=i(UL%izfPp+ zK!tW&toKC&D7STdy20%$N(ODQ-qNiG8T=>wnTwK~xx>mQ zA)%eTsXzIly{m^Tn%H~p(QnhFL2WdL)gmqso{^3%!9Q zi1kH7i)B=4vtitlRRRAZ52d6jp@{+uO1;fm<@eAWIAmg)|AowReKuJyc}|cN-SO5D zE(KHrUByQlw1D)E`;w!Z`zeQ;~KX4syDv(8Qj=*o6FZHa`(3)pUh0+6aoU-osqss@n zuDZLaLZolnuA)OMRhX+E;{RVL?YfZ~gG$gSQ=^JyVKuOtST>e}W5D3#=8^8oMa_CBu+djuT)Vu#Q+a?0T#x_806HtPgfOb`LfH8-xwU z?wc|@gell^5O?9&2y7IVz{X2I_ypCttq(_5*PQejoF#3qyGbRtZ`-l diff --git a/data/Fig1-designProcess/distinctSubset.pickle b/data/Fig1-designProcess/distinctSubset.pickle index df7d64781afea6b6368c8613fc79117c23c3a3aa..a98c20d8f33497f09b1792272e94fd5974c5cd71 100644 GIT binary patch delta 1439 zcmXZQe>~K89Ki7}&N&=+jyoiC@}pFD>XfZXpSPG_S1J{St@(AUTaw0X#J6TE^P?=p z79p}d6bdVC@;y8j9uuh^Wo<%D8iisPJ+8CIW4&MhJRgr&9lwr$X^9TKSSCw~xhaI& z=4e-X9S>GS2q)E24#0N3S{DZm2`aKT$=_uQrD5+qVaZq!**&M-A%0APay%sY))qib zrtORvu!q6DDGLAdlML7NUk#&J3^R_rWaXO$@@08<*sUlkNxv=BPg~am(T2j`y$+)*h0L_}8x0X+vL3M__&~5o5=uGS30ed?V>PP?0Qzct4eXyNMBmI{B`NtsEnZ zxBD(hF{613%zxL@t1Nz|i|6hq{@v6FiyMwyqP9ik^&L=cb=sq`t(0q2X&cG-CX z@YJM4N+U%;B@Mg%wQmtrT{UOl&1AuvpO#yHFlYtd2V>sIttqH~@n~g^1*JN~>F!;% z`w>~1lI}#?G?;?#x0^ND-U5giam(tT<-qOL7mdbB#E{o|Z-YoWL7ap4xNp7BhaW49 zWoM+*OnGXD7rW9LE_;72xEMD}lG1E$Mm5Y50Zaed=}>bh*j5_WCD#Qj^@E<{S}Pd# zwJ@)o))Ecd>tyuUA7rj{ldEwj3l7E8wB&1D0XX)RZ*0pphqxK`FQ?M!c#C1hTx%D1 zH!u=uW187jHuUax>PkJ^!gQqcsI7CS8%J0?9a^7y8wWK+jZi*nhFYLP)DpEpZBaYa z5nYD5pwhSI`?1aFb@<*#J<#>&Ml=8oL^q?s=uR{ojYXB{7ibDfzm=xG!jXXL7XUvG-4#nFgfL4QSC(CcU`%AjreZ3c1w0knq8ssI20 delta 1452 zcmXZaeKeGL6bJAzYfO2YF*9CA40)-Bwv#BT{oRD*NTqgFE331WC`ZyFY92~zshnl7 zy;*}DsU^|2W!3YjwzOH+HdK`Lb|%%R$$PY{-R?c-dq3xV|GVeh3VsE@(q4x$PHZ#D zXf*@*&JQC|%>wv*$>8$W3>Uh$-z#p&wSe<~$M6GeB%tTPmywJA5MNDR_UUjgWOe^q zQ1(;;nkUb%Mx=AV|MCuT|Eo^AqwHu*Le>}^*Q8ESc-n!h&q48HTLVbR>M|b)`<-y# z-&j$I88}g*>(JE{IxCkmx2|DlLgJ2m7(4 zi+MLSq{!>M-nd8rn%H5no1>Nv==zEJ>x~J7+^lk#4_p|!QoqM9O$@yE(S}2hL~wP& zDSk4ohmKpna4{==kemq^UwbN00E_xx_T2Ur097rh;SpOFDmJSQ4_H>L^)9al*6NS}mW}-0Fzu+(j(Aeu*ku5i<+n&9UWBbYiRY< zT20wE9B|l8DYvfVfy-xBd!l(WAY1-*mj1lgw8f6i)H5#VfJfAdKfcW{gECW9YG{cK zT=4X1+OTGVuwKcsWSb4(Szl}Xp8=C}_~N-+V~k&u>(-;%mX0pEaAeoHhkK2f-75Bq zRZap3PV#xMXZm98+=oRn#amK)vC^=)kp(~0-tVh7874u!?X=2PP2`vB&aL}|%|y(k zoVJup*-+@;8=aR@PVVj;s&troK?nM-QoW1kLB70ozmIT?EPGq|p+d_C?+KfdV|7C` zZOMOd;-Dd8XabVGE~|;aGNx&EcGg~W`Ur%ajMIG2Ixiw`X|$C$!%JJ&-HQQ+AX)-F)U(&eB;6* zr=OK_*J}N+ks0f{f z+M!OU6m>-xqDxRebPXExQHu2i79r>+bSD~#?nYzKz34u4KN^o7K$Fo!s0^k4cY3E{ zaRg06)6wJT3G@`2g=V8UXfApdRiGuP620)B8>dr_MFn~VtwOJ(HE1n*3uVyT=$)K8 GZuGxvJ>pXU diff --git a/data/Fig1-designProcess/fullData.pickle b/data/Fig1-designProcess/fullData.pickle index 4ca21bcc5aaee9ed6fbec1bf077fb7f615291d82..3c96352c4829f171db0db65c3c245b20052445a2 100644 GIT binary patch delta 3238 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 W)%Ir#L9D3#LuES~itaF0iv1s4f}4>5 delta 3238 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 diff --git a/data/Fig1-designProcess/hullSubset.pickle b/data/Fig1-designProcess/hullSubset.pickle index 757c46dc1d4cb2acfa958aeb00f8730d811fc9d6..bf2e9bc2cb05d2fac946c0d945b780284117e1f7 100644 GIT binary patch delta 316 zcmeytwt}6dfo1C4i7ZbUc_zLxsXvf-^2fgrg~#?U7(2e2-}toua^}w%^U}Zjcl_BJ zu;7EBL$7{gN5WGz2ifVe7s7rqAF$0U)YWBEbBMi|mGnlG;eZs6C;w&_QHS3D`yYqq zGC8bz)o;AJ=i`3Q!o)0>DU1%64A*cypQGSVGV%9|*DD4HMqoH&bl&*l%%}{za Ql%5Zz*Ffprlew950gk3^&j0`b delta 268 zcmZ3%{)3IBfn{p$M3$$FToYfJ)GzQ@pDO+K)r0-_R<`Ds_y5?>{&T0vyk(3BJU1$b zXsdHL9MQgQeXLc%;lSHHydq_44pL`C1gHA^+y89gGVQH1B^?^9nJ;SZS9LHIU9n#@ zT*%>vtmOHI4#o^sdR)%((y!*xb!jK6TMjk-~m!V0V;WURp+BKYc1F zY+(_H<*!oH1!Y#0m4W37GV5xi(^z-X>9RY$gw0}@mReBX_dhRqJ6H#MJz65()-6cl z5&~g9G^g5DEX9fc&3*dU69QKGHP4J07Yb5UzB~(y)a(Jb{Nu2Y)WRD(RBD{dTJWDN zQHGzNj83kO>=$emnPq;Dd;;S+xMt(4DEzknz}>u}L80DztR*K|gKd}n*^=N-!mIlA zjscd1;;nt$EgKbu>hjt4p6VcY-P-yw4~tHVw32I(pmqG#%DQ1S_7?ljyAy-3${Idx zX`>8f#>1tX{xzV;)%f(Esvu}RX*XwZBf`B0v(jCY9L$A92?+`V8ZVC)xA`*&aCL^x zZ<3=xQo5DTRARfuE`Jyt2;(It+@llKDErdhzotNn682CH=TyNFDy`~T!eb<&vpFP< zLsvylaa#rh=VNbc+>=RRYtO_`*K;Kf4l4(T_OodJz|MT;uZPoMiwM52M~$gfnU@ra zxP2wl!*8fi_ac5*`(qx{?%sM+`&o;Zn}5n~4%K3#dye&m=nKG~rYnI1HIc}@zIsF8i=vc>jrbx__4)%R&;&} zM#Qh(A@+Mb28>y=WHud)AFQsn-Z5cq%Ziac=@i`W5v_~lQ*h^D>1%I?4r61MUBm4v zuz%^VMX_OcCoE3?qc;kQcgaOta(Vo{A|ci>qQz-x$J)w#Jtis|E;hZ5Ku)^3TNcM7 z1HCyl&q84{w8@>O=NxWc@KZ=c3G+P}sUVdkORC5ak|Wimh72QPNE5k`Od;`Iky%V* zDY=YHBiE4|$ZT>GnM)Rud&nc?QSu~NPF8+1nPF;a)R7m+2GT}0kypvqBbORLRQ1NQIM+{(&;b~F@FgBoTAjd>N$6jNqx_I!xci@x@V+RBExr)q_ z-`j4D2976I^1;xlWa(NG%Cx-2&m=-nm7f_g1rZQ%`!~7wfdi*jd_ zA7=2!nN>0o9N6F&NaS%}*!+ZPzCIZiwllmx)^EQUio(M>+*_ywuu2H;wYBo* za%V_25@WhZ67+d}!`xj0meF->bc__*k9d?nCM@jNk0*|H_X)r~e`M3gXC`)0L7(Ep zxGjVv(mUH+zO!CU7rnQyqhQ|esE5|kGz?n~F{50BnYBNx(cJR4($|{iPv~8Rpw2$) z-;g8&@k>)*?~s{&Qm4dT!$s4kots zN+V@75Wo}*>f)56Y>FMTwLxwL?Lj5RAJZN6C1oQc$rh=8UHF=w@q;4R7G|vYRcQ}x z&f=%)BNXTg6JiB#9HFDas0>agV7*~5DL(fP>o-fY)c&{~41JsPU}3>@=wFgOyx|i8 z#R;FKVJ$z|#Y1I0=VXhMzNy;UhU6TGsYy^7>VmqX3sFyW5h_Q0P+v3{4MkU?YtV=( zIbsWjt>|_%8Qq2MLDSI;Gz&e3=AgM~5voQ@(bNA8A_xtJb7&2E9o3=DXbXDx^dK+o EFOrrmsQ>@~ diff --git a/data/solverLog.csv b/data/solverLog.csv index a43d525..f2be742 100644 --- a/data/solverLog.csv +++ b/data/solverLog.csv @@ -203,3 +203,7 @@ Uni-criterion: clusterCenters,greedySwap,1000,2,10,0.13824820891022682,0.7651631 "Uni-criterion: distinctness, distances",greedyMixed,200,2,27,0.12416926166042686,-41.35106343740662 "Uni-criterion: distinctness, distances",greedyMixed,200,2,14,0.0512898382730782,-42.63467324402975 "Uni-criterion: distinctness, distances",greedyMixed,200,2,91,0.3911852678284049,-69.8726033176274 +"Uni-criterion: preserveMetric, hull",greedyMinSubset,200,2,12,0.10196879226714373,0.0 +"Uni-criterion: sum, outlierness",greedySwap,200,2,40,0.02950233267620206,-83.70271953374831 +"Uni-criterion: distinctness, distances",greedySwap,200,2,60,0.1577538326382637,-74.06808510204883 +"Multi-criterion: 100*(earthMoversDistance) + 1*(distinctness, distances)",greedySwap,200,2,80,8.527639084029943,-38.28864852224051 diff --git a/figures/Fig1-designProcess/express.pdf b/figures/Fig1-designProcess/express.pdf index fdbaa3f0db6c24f11ef6759fe88f1827817b0087..6c704be7940ccb19e1ef31cf33134e6b8605f608 100644 GIT binary patch delta 8210 zcmZW|by!qU*DoN7fYJ>TA_6kfDXnxjA}}CbN=giIR8l&maX=arkWfTQkRBRoq+#e9 zI`8&-@AKU6zRn+e_St9c^{aKJ1F^3HvA@J)L&h=I)vm#3HBhThBoo3B^G#W*tvu(a z42dXJY$&s4_{Lal#xWHdjW(7L7>un=W21E;X(cbR9h0y!H7I#ditG#68-}h+T!k+nWO? z#RZs+L}x$0lb(f2NP;avm($|s<^?1oSORa-~Lp zX&v@36%9$Dnxd~c$b&~u)HAi6Nuf zrGaWCVcQM23Tyw^Nl}i`b%LabySoFHoRSGPxIC*G&z_HrZ1j{HchrX?s4E5fQ-ZRmAa!MiRde9LeG6 z51m9k$&8C&o1!K#*J|!`6JXcR6g|;-1<8Y3St?=f2Ziuat>OuPm9}p ztwt}1<12bwveqQvT7_E4QeU6H$9)%#J)!cEW1lW?Q3?O^r|4Yw-D3 zyPHd7{ElX;?7?>n(LMtn42N?R;tp3iVVxwm8&1dl-X?`1UL5kf5~e}ZtR{*bqLDuy zyBRmdD_>h9=?FfWd3+tVX2cuq<58ioW6CED$9?UNch$+_=qwRn%101!T&yrxyY`gR zvzc_!NJ>n$S@AlolpE@|Af61{Y#C)C=Pnj}rwWhjvfVV*#4;j$zsLIQr(#xMSXJ*` zL1Ml4L6j2<;qBvnZ%p!g^nD7ml=<9l6H`R$bY>4#p{{q&5rtc1SJb;E;LOX`y){zc zoDc43<1i#OY0vp8b1yR}mKOT~anuhJT&mPx`wAPjO@pJPw=|w5Zd8Zb7?LFMlF0A<1LHwEe?U>v-*+e-s=n*nhug47-UPaiaCs( z!kiax{#?RQ$h91LF3f+6QSnv4HMS-im*Cv53@!C^yo3}wO4B-`VeX+h<3b*545XS$Ma9MeAtQDHsY z!JT83BOHkkd3a5yoFDzVj00YNO|aZ1oi#Q!S7qsvh3H1?YbeM2?RC$ao>Fub@7)%| zohyhx!Xu1qWvk(d2g${~^czbQ-uP)RmT~D6zUx2uEt{I&$8ta?>ztPsPblm$?CSQ) znATXY!YX($PtTUwAPzG1P_Vj~&IdW3y*vZ>OucW zS3^E7Ev>c3Q*%|tXE63{!tbQv`e~I)OejuSk{6Ubcag=`BAOYvwh# zG#{4|W&1F2H&g4F|2TNS-$mzcBI5ilYMgN(rz5A?+Q;Tp7q6L===KVgx#p7JQUUgtUz|fGY!}`DvABRj?#sN`HK7^Ieh6D5!h8Shk8O7@ zwKY8}j>R$Z%bV2{*e81(ERm(1g}{|3No{kc))k-?Bu(B2a8ss zd5LtcN(RT>e#Po{y`a*3g2j@Hxc`DEbLeoJ)V8eOVWDJF1Rng;{Q4?Kg*|{lSehBaxKwD3YuH zO6YJ6iG%BD9biBz6a9?uM;4YbHkVreTM4&ixthBWI}=}^Y!%8c<4-MDak0%k{AHhV znth9s+h@hlj$XKao=QLYJ7?|93bEWly|=o$4vPBub~-7t@4V=Ksbt9D$4?Ob=q-KI zsw|a4s`^xWVz#lxo2uwVwyY?B>H@z`Tv(5h*e*$wLw3Aec%uF5JUbS>I*AjPMYW1T z$!t3Z=yl)^qA>mIO7t8PdID;Xu(g)Sg6H%e*U2p{I@z4CsI|??myq$fJKPuvmxSfb zITiG}bTVT#%$JkK+k8^X>oU42yG9`L1{u-%ASy}L&NIt=KS6~ z9#8dR4%is|Pw%o{>xRoOi^A!O=WySJs}$P5$At(TBv%$>=VK(D8LVxJ0Fng(+Gd>R)n?x4D>9FTE@@sz62qz5w zjyDe#kqAE1HWYe7OcxlKaxdT1OO)V3Vf2fD-E`kkg-{(^{SezVJqpIz`gb3$V@Wuu z*U$zJ1Jme*i+ zsEb<1r)B%-Xg%608qOzkBd|5>)8O-UoF$oJ?hj7Gg>xngX5@++U|aak=dElkhnX!3 z=+cIfN8zr{{AMWL7Hl#SfJc%(q0puYbe~VA%DRzolQ`^qn+$=*$LEE|0y|{g0mLW_ zq=@T`!xYN;b~@oTc4b>p9ocmzyYFeFcD%beivq+ma(2Ghb6FYJ&NS#a8+aAV@kpDE zR7Xhg`Ey56r8XTwDQbH9GH=)ONd@If}mPy*YSi53=vGc)pyLVh2}@xT!|on8uYxnT(Z#P`oU9 ztMif;k0iaugV9R%`$~{8t$iBvtNlsOYs6Fb(MTaHd)Be%{nuBvgt7J4ng|IxunY7A z2o`7A#(s(~t%tLwP2_O8b>{R3{|Y%0@?nnc+NqwnP7qh>GvN{OwDpOe_3e5^_jD-! z2CI4b3GDUrtZ$ELZc*cURTZ1EwM+a!!rORDS4(IfXGy86&x=1z)7$4mcx#+$2x0Nc zR$}W{{wAm+$q9^Mvr|)=ZMS)>K+8jM9MnK=fjfRf<>R?$j{m^jw~@hhWpCm2RvBGf z?mBtzow|Zb8L?Tl#g9iS$F;iTSLceLVV6$9`_=CY(zt!U7ps(T!s>N~jE(dZ-5f}) zV+z|3aXjPM?QS5#y6~(A#XAW1UB(&pcjyW}R>gR+J9^2w_ciMXeRd5ZUL`o3z}6Bn z;i*znkD<87S!*c&<)n~JKG@CneJ&wfabr*sFM+Y1^VCl6rr{xXS}8eCf6nPN_Zh9nq1OC_eee{ttd|Zhov^=a*k`G!?|7{Wo`r4lEiM2^mw&Mi8%;B$#Sv@-uUq=(V#peng?plX8&{8Rj_qVyH_bBs7w1{|o4VUjR z9h&sBzrWE;S(Gm4l|O_g92nB&hAPhpf0V;S2P<_M{|G3{O&c}ow?=n(x(OEcyDHoL z=&10Cy=!9S{z}y3+VTza1f6j|_{aK>XdOItK9z-##I@fL7Q90zvfQ<`UV!7K)zE2WX1vc%Pq~ETNeKjsizkUQB6ql+y-6*(68cHhUTNGy)4QPa)4hw9f7hl?rtZ*IkEKWG*>KjgoH^FiSI+V-Fd%=eD%|^ z;QeUVpK4q(Bi!&D8>gq~ogB?^4%@4qoze3b_L&Bwg<}KjR)_|YU$=6+@jj-0KIo@X zQ8TP&_9vmN=znjPM*K81?zpIEdhJSPosdc`-)`rkygID`n?gE`ad(w>g~_7dj>18y zsB8H$dqakt^OJ4Ty%UB_h>UVrA|Qbm_O5y^Uvags*L3@7KIbr(e0|nXW8|+DSgPka zKhG!Xp+ZtVj~7#SEG^n9(`~V7hJ7O{lADAyB>M(xLp5(>BBx>;x=2%IjJ1^?OG-f( z4Kq8%O7~nc!{sM-7EYO;`duF7s-J&3>~_PaG6Y<_tdcO(rQLfWXu!vz zrKHf!Sr@)-uc{3zNbhSa6-j{r`C0946!0sTzAKp7S)!Dza0$iSv1JDs)C zL>Sz3F9tVT#X&9iHzZ(03K(s|z{0=*&K@G6=x#UoRu>H2KY@Z7-e2s1C07CZj@wm< zM$`2*V8L+(hSU-Ry&;=$o0_qHfWcA6TA5M5-3g=Km_os9KYiy%1^@BpN9CP?N5jYE z$wu69OTZW3AN;7q)@|#g2z?-Xa|7V|(HPqJIKJ@YN7XC?Eznn@P3t5s6hKECgX-30 zK#PbQpr!Q38I=lT0P`A_0WQNY;Qwo2wynZ)Cv4OJ0(zB`fJ)j94VxN%b6~_6h^Uuk zy%Uz4C` zb+4WqgS>Wt{dt^#>RXcN?mc0rF(B!D8iX}5+XXZH?O~N9@DlVoSpiIgxio>A-D)7c zWy?AVH3EVSu?7mcoInF753o}eQ?&76%><7x+SWT@&bm#Yf5T^h$@eSH2;vR}DG{EF z^P_~Oz+g3h0NHM^fvyp}e-6o5yMMihk)t}P{Z&4 z*D@?Wo=Ot~(ABv8N1_q8#vYi23lNR7;tW{kz9$=%X8evb;tm}L-@#=w*ag{w8$|P6 zFx$!v>m=3pAnWz8S3H$t)E^15vFd^@$U%fU~YVFE8 zkecvASt%%HBGSGlH#4gW$wF~y580{RJ3sHZx!iL=(=02<5#qAbQeGt($mHo9 z!7|IqmP4VZz3kUGV)X+B-x5TK#Ik>*2(+iT{h5t0oEgd37R~+evmQ~B`abk*Jg+65 zQDNcsqprQ^gW0#)FtWzs0zNzslG_FpKb#|m9F8UUXjmA@d+kb<#zQ4p7zIRE<+M{00@SwF8OOn&RjZ0ncVB|@+cnX`pWv|W+!BuMR zo=QQ7Z=MB%trMJ0EnnfC@zW72;wA3Mtc8YWS(W`+k#fbdxxd0;QCj1W(@$d^Y2H|#8H56}-PZ=w{d$X>az$NP^#UmL%R`Z!URVhaHUB6@P zcc<8j@}~;4UH!%EHN-rsRuGwRdr&6w{7TD1;|s%5PJivnNsfQ4D|Bo@<^(;xNbc+{ zh^g>IT(lOjAGb-o$z9!MJgJq=c#q!RV5NsDMz6$I#rj!N#+3Rn6MS2FXq1~KLW;*L z5ACCzUBB=5>_RdZeUdcbyLwVJos8^j-_1p%^d-U5R3fr3{R|q!Sl6>kni)Fhp^uIy zRQd{*xNA)#S1Kl#c!_F1Tx_fKCHMSKIk=1hn|LqKs%|V9Sw{0E4%sI*r`%_Y_8r8G z-$m~G;ZvF+8eVQI^`X-dgP39N=zYIvIl#wkI04BM0-#mDd>_Qv1HjB9&pfn<#0;d` zXUO_84~>~_*!S}+WS7j0ng@_h;O!6sG?RM`YI|0c`>2`31~FeNLODmIY%y?>&eSaykN>LjGdR-B~@^@Yh5%n4{qcDdW~eB+o`0 z@Zb-4Y#<8Wo?(lF8}~s8 zkr8-{n+POmHY6i?AP);JNi)Yi0}#>xfcyj^b|O(kyz~eXUpcAoDAeUTp_48jq()hvKB?Mgn^Ozs&$tVK(4R~J-v!``h=6ngFvb{b5N0?nkSJCM@|~TDLzc~L zDfLlrEh_cd^8D=@^q1S;5##0s%k%_r(gg(X>|LFVoaq|XKuGz{P?Ai^`~qW|HK)=y z8h2>m=JHDiMEDs{BV2L=^9b?%0TXxy+?kXIE*j@~=Aw@_y#S%TM}ru#pAtazI!GmX zH33+LHw&_^07x^BMoRYmT;lQRegzX^LrQE-qyMY~t)L_RV0dBaFfB{Ok z2Kux8z@qpWoZY?vaBR}hU%zF6YRdy~_=pj3T7UgF@w!#Oc(4L|q_{nC$e31X69kb! zQ{wxJQ~#^@nasNL(RX5%WyR$m9wN zSn?P4CV38yRuibgpUQb&5T|)c$dYr_vit$p;Ra;=WXR1>SkRe!oTn!hQA4LVUY|Rl zzB`GY@Tq4nNHridkY#_$=y!IKOf^(07yB)9#NMP8WkF-FKA07U@L*z~culIJw=OCf zCWqB(+SmH%_Gnl<2c(wOD*TpAr$+1S%v*{|PtU~PC@D1Ob!U}HEYa$DHtsT6o3WvO zcR$3gvU#JCQ+}H$_Rq80uV3@6$;MG5Mbe2dBWK&WN!RVV+5+_y1H-MNQvJL2jytx^ zHM&fkOC!(QX5Tv$*|v*f>G!9zVZK;|#EdRDYD@N}sr3^nkI&VM_8Go{XC&|Z zX%y`n`0notCwlnYg3_>LH*ilWMrsN}F!B&OP?%{+`eb#hAgFBt?~a=DsdKbDg9Cwr z`7crZ*+SZ#at8G(@7n##L=`P6YxR41`1o|R#`jsSYajyRj5d5%{o`+x!)>H)<#Et^ zMVhn|*T}r!wfUA)EW{bSf8^=j{-Cq--4MQsILjAWr{GHA!UCl9O*o4#Utr6{WS6ro zq`hy3c-+m}f*5ex?@BsKsPd3yfJ8z0IqW1Z82E`Wci*cz4-s`XW z%vDDtQUc^;r57;0_NAU{iVydXemkCtLRIvfDeDpW8Zy*EgpCO_`w0l7dQZ2GS97_j z!+8tMb!PnHT=hXU{f+KkHd`ClUso617ELBzHs#BV_foE2Nd{jROXa6KFdR#NNnp8^ zm062gD0o_WE#AjqrHbi5k5hF{sc2=bx25* znfLFH`6V;K|7`dK`9uZ&IpgOO`sYkQNaWu$k$?LMh>87I9RL#kPrn2%85SH7-UJPq z`;g#&m+=V-iVFYNRX#xx!G9oxc=>q$yH1E-1Q_)9_y42`2?+@Pb0#A89}MV!6$*$5 z|8rSDkoVs+;eUPM7Zv_*UwB1%#r`2EAol-@V*ph7_{IJ&oBu^dn2%31AzD@uUqpz2 LjZI!tf#ClD^rgjg delta 8162 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 ZAR~4MDH>ILPl-fCh?IjvK~s_R{{X8aOXdIo diff --git a/flexibleSubsetSelection/__init__.py b/flexibleSubsetSelection/__init__.py index 5dd7be9..7f30d3a 100644 --- a/flexibleSubsetSelection/__init__.py +++ b/flexibleSubsetSelection/__init__.py @@ -9,6 +9,7 @@ from .sets import Dataset, Subset # Data management classes from .loss import UniCriterion, MultiCriterion # Loss function classes from .solver import Solver # Solver class +from .color import Color # Color class # Import sub-level component functions from . import ( diff --git a/flexibleSubsetSelection/color.py b/flexibleSubsetSelection/color.py new file mode 100644 index 0000000..8984cdd --- /dev/null +++ b/flexibleSubsetSelection/color.py @@ -0,0 +1,73 @@ +# --- Imports ------------------------------------------------------------------ + +# Third party +import seaborn as sns + + +# --- Color -------------------------------------------------------------------- + +class Color: + """ + Create and store color palettes and color bars for use in visualizations + """ + def __init__(self, palette: dict | None = None): + """ + Initialize the class with a custom or default palette + + Args: + palette: dictionary of color names and color values + """ + if palette is None: + self.palette = { + "green": "#8dd3c7", + "darkGreen": "#338477", + "orange": "#fb8072", + "yellow": "#fdb462", + "blue": "#8dadd3", + "grey": "#eff0f2" + } + else: + self.palette = palette + + def __getitem__(self, color): + """Returns a color value from the palette directly.""" + return self.palette[color] + + def getPalette(self, names: list, colors: list) -> dict: + """ + Create a custom palette for a categorical set by assigning colors from + the default set to a category name. + + Args: + names: List of category names to assign a color to + colors: corresponding colors to assign to the names + + Returns: dictionary of names and colors + + Raises: ValueError if the names and color lists do not match + """ + + if len(names) != len(colors): + raise ValueError("Names and colors lists must be the same length.") + + return {name: self.palette[color] for name, color in zip(names, colors)} + + def getGradientPalette(self, color: str, number: int = 6, + type: str = "light") -> list: + """ + Create a gradient palette based on a base color. + + Args: + color: The base color to create a gradient from. + number: Number of colors in the gradient palette. + + Returns: A list of colors in the gradient palette. + + Raises: ValueError if type is not light or dark. + """ + if type == "light": + return sns.light_palette(color=self.palette[color], n_colors=number) + elif type == "dark": + return sns.dark_palette(color=self.palette[color], n_colors=number) + else: + raise ValueError("Palette type unrecognized.") \ No newline at end of file diff --git a/flexibleSubsetSelection/loss.py b/flexibleSubsetSelection/loss.py index 2e7ff11..a285145 100644 --- a/flexibleSubsetSelection/loss.py +++ b/flexibleSubsetSelection/loss.py @@ -9,7 +9,7 @@ from numpy.typing import ArrayLike # Local files -from . import sets +from .sets import Dataset, Subset # --- Loss Function ------------------------------------------------------------ @@ -51,7 +51,7 @@ def __init__(self, objectives: List[Callable], # Generate the combined objective function self.calculate = partial(self._loss) - def _loss(self, dataset: sets.Dataset, z: ArrayLike) -> float: + def _loss(self, dataset: Dataset, z: ArrayLike) -> float: """ Compute the overall loss function by evaluating each objective function with its corresponding parameters and combining them with weights. @@ -131,7 +131,7 @@ def __init__(self, objective: Callable, solveArray: str = "dataArray", self.selectBy = selectBy self.parameters = parameters - def calculate(self, dataset: sets.Dataset, z: ArrayLike) -> float: + def calculate(self, dataset: Dataset, z: ArrayLike) -> float: """ Compute the loss by evaluating the objective with its parameters on the selected subset. diff --git a/flexibleSubsetSelection/plot.py b/flexibleSubsetSelection/plot.py index c228a2f..3741718 100644 --- a/flexibleSubsetSelection/plot.py +++ b/flexibleSubsetSelection/plot.py @@ -15,75 +15,8 @@ import seaborn as sns # Local files -from . import sets - -# --- Color -------------------------------------------------------------------- - -class Color: - """ - Create and store color palettes and color bars for use in visualizations - """ - def __init__(self, palette: dict | None = None): - """ - Initialize the class with a custom or default palette - - Args: - palette: dictionary of color names and color values - """ - if palette is None: - self.palette = { - "green": "#8dd3c7", - "darkGreen": "#338477", - "orange": "#fb8072", - "yellow": "#fdb462", - "blue": "#8dadd3", - "grey": "#eff0f2" - } - else: - self.palette = palette - - def __getitem__(self, color): - """Returns a color value from the palette directly.""" - return self.palette[color] - - def getPalette(self, names: list, colors: list) -> dict: - """ - Create a custom palette for a categorical set by assigning colors from - the default set to a category name. - - Args: - names: List of category names to assign a color to - colors: corresponding colors to assign to the names - - Returns: dictionary of names and colors - - Raises: ValueError if the names and color lists do not match - """ - - if len(names) != len(colors): - raise ValueError("Names and colors lists must be the same length.") - - return {name: self.palette[color] for name, color in zip(names, colors)} - - def getGradientPalette(self, color: str, number: int = 6, - type: str = "light") -> list: - """ - Create a gradient palette based on a base color. - - Args: - color: The base color to create a gradient from. - number: Number of colors in the gradient palette. - - Returns: A list of colors in the gradient palette. - - Raises: ValueError if type is not light or dark. - """ - if type == "light": - return sns.light_palette(color=self.palette[color], n_colors=number) - elif type == "dark": - return sns.dark_palette(color=self.palette[color], n_colors=number) - else: - raise ValueError("Palette type unrecognized.") +from .sets import Dataset, Subset +from .color import Color # --- Figures ------------------------------------------------------------------ @@ -260,8 +193,8 @@ def initialize(color, font: str = "Times New Roman", size: int = 42, else: plt.rcParams["axes.facecolor"] = faceColorAx -def scatter(ax: Axes, color: Color, dataset: (sets.Dataset | None) = None, - subset: (sets.Subset | None) = None, features: (list | None) = None, +def scatter(ax: Axes, color: Color, dataset: (Dataset | None) = None, + subset: (Subset | None) = None, features: (list | None) = None, **parameters) -> None: """ Plot a scatterplot of data features on ax @@ -317,8 +250,8 @@ def scatter(ax: Axes, color: Color, dataset: (sets.Dataset | None) = None, **parameters) def parallelCoordinates(ax: Axes, color: Color, - dataset: (sets.Dataset | None) = None, - subset: (sets.Subset | None) = None, + dataset: (Dataset | None) = None, + subset: (Subset | None) = None, dataLinewidth: float = 0.5, subsetLinewidth: float = 1.5, **parameters) -> None: """ @@ -357,8 +290,8 @@ def parallelCoordinates(ax: Axes, color: Color, alpha=1, **parameters) -def histogram(ax: Axes, color: Color, dataset: (sets.Dataset | None) = None, - subset: (sets.Subset | None) = None, numBins: int = 6, +def histogram(ax: Axes, color: Color, dataset: (Dataset | None) = None, + subset: (Subset | None) = None, numBins: int = 6, **parameters) -> None: """ Plot histograms of each feature side by side on ax with normalized subset diff --git a/flexibleSubsetSelection/sets.py b/flexibleSubsetSelection/sets.py index 44918b9..034957e 100644 --- a/flexibleSubsetSelection/sets.py +++ b/flexibleSubsetSelection/sets.py @@ -19,7 +19,7 @@ # --- Dataset and Subset Classes ----------------------------------------------- -class Base: +class Set: """ Base class for Dataset and Subset providing shared save and load functions. """ @@ -81,7 +81,7 @@ def load(self, name: str, fileType: str = 'pickle', print(f"Error loading file: {e}") -class Dataset(Base): +class Dataset(Set): """ A class for creating, storing, and processing of datasets for subsetting """ @@ -188,7 +188,8 @@ def scale(self, interval: (tuple | None) = None) -> None: self.dataArray = self.dataArray * (interval[1] - interval[0]) self.dataArray += interval[0] - def discretize(self, bins: int | ArrayLike, features: (list | None) = None, + def discretize(self, bins: (int | ArrayLike), + features: (list | None) = None, strategy: Literal["uniform","quantile","kmeans"] = "uniform", array: (str | None) = None) -> None: """ @@ -267,7 +268,7 @@ def __str__(self) -> str: return (f"Dataset with {self.size[0]} rows and {len(self.features)} " f"features: {self.features}") -class Subset(Base): +class Subset(Set): """ A class for creating, storing, and handling subsets of datasets. """ diff --git a/flexibleSubsetSelection/solver.py b/flexibleSubsetSelection/solver.py index d76aaaa..cf65869 100644 --- a/flexibleSubsetSelection/solver.py +++ b/flexibleSubsetSelection/solver.py @@ -8,8 +8,8 @@ import gurobipy as gp # Local files -from . import loss -from . import sets +from .loss import UniCriterion, MultiCriterion +from .sets import Dataset, Subset from .timer import Timer @@ -21,9 +21,7 @@ class Solver(): solving algorithm and loss function, applied to calculate a subset. """ def __init__(self, algorithm: Callable, - lossFunction: (loss.UniCriterion | - loss.MultiCriterion | - None) = None, + lossFunction: (UniCriterion | MultiCriterion | None) = None, logPath: str = "../data/solverLog.csv") -> None: """ Initialize a subset selection solver with a solve algorithm and, @@ -48,7 +46,7 @@ def __init__(self, algorithm: Callable, except FileExistsError: pass - def solve(self, dataset: sets.Dataset, **parameters) -> sets.Subset: + def solve(self, dataset: Dataset, **parameters) -> Subset: """ Solve for the optimal subset with the algorithm and loss function for the specified dataset. @@ -62,7 +60,7 @@ def solve(self, dataset: sets.Dataset, **parameters) -> sets.Subset: with Timer() as timer: z, loss = self.algorithm(dataset, self.lossFunction, **parameters) - subset = sets.Subset(dataset, z, timer.elapsedTime, loss) + subset = Subset(dataset, z, timer.elapsedTime, loss) self.log(dataset.size, subset.size, self.lossFunction, self.algorithm.__name__, timer.elapsedTime, loss) @@ -72,7 +70,7 @@ def solve(self, dataset: sets.Dataset, **parameters) -> sets.Subset: return subset def log(self, datasetSize: tuple, subsetSize: tuple, - lossFunction: loss.UniCriterion | loss.MultiCriterion, + lossFunction: (UniCriterion | MultiCriterion), algorithm: str, computationTime: float, loss: float): # Write log entry to the log file diff --git a/jupyter/Fig1-designProcess.ipynb b/jupyter/Fig1-designProcess.ipynb index fe530e5..cf50d05 100644 --- a/jupyter/Fig1-designProcess.ipynb +++ b/jupyter/Fig1-designProcess.ipynb @@ -179,7 +179,7 @@ "outputs": [], "source": [ "# Initialize color and plot settings\n", - "color = fss.plot.Color()\n", + "color = fss.Color()\n", "fss.plot.initialize(color, font=\"DejaVu Sans\")\n", "\n", "# Plot the three different resulting subsets as scatterplots\n", @@ -306,13 +306,12 @@ " ax.set_xticks([])\n", " ax.set_yticks([])\n", " ax.set_title(titles[i], fontsize=subtitleSize)\n", - " # ax.set_aspect(\"equal\")\n", "\n", " fss.plot.scatter(ax = ax, \n", - " color = color, \n", - " dataset = dataset, \n", - " subset = subsets[i], \n", - " alpha = 0.6)\n", + " color = color,\n", + " dataset = dataset,\n", + " subset = subsets[i],\n", + " alpha = 0.6)\n", "\n", "plt.savefig(f\"../figures/{directory}/blend.pdf\", bbox_inches=\"tight\")" ] @@ -387,7 +386,6 @@ " ax.set_xticks([])\n", " ax.set_yticks([])\n", " ax.set_title(titles[i], fontsize=subtitleSize)\n", - " # ax.set_aspect(\"equal\")\n", "\n", " fss.plot.scatter(ax = ax, \n", " color = color, \n", diff --git a/jupyter/Fig2&3-objectives.ipynb b/jupyter/Fig2&3-objectives.ipynb index e826dbb..a026c92 100644 --- a/jupyter/Fig2&3-objectives.ipynb +++ b/jupyter/Fig2&3-objectives.ipynb @@ -383,7 +383,7 @@ "outputs": [], "source": [ "# Initialize color and plot settings\n", - "color = fss.plot.Color()\n", + "color = fss.Color()\n", "fss.plot.initialize(color, font=\"DejaVu Sans\")\n", "\n", "nrows = 6\n", diff --git a/jupyter/Fig4-performance.ipynb b/jupyter/Fig4-performance.ipynb index e8ae3a5..3a13bfd 100644 --- a/jupyter/Fig4-performance.ipynb +++ b/jupyter/Fig4-performance.ipynb @@ -113,7 +113,7 @@ "outputs": [], "source": [ "# Initialize color and plot settings\n", - "color = fss.plot.Color()\n", + "color = fss.Color()\n", "fss.plot.initialize(color)\n", "\n", "# Create figure\n", diff --git a/jupyter/Fig5-scatterplotOverdraw.ipynb b/jupyter/Fig5-scatterplotOverdraw.ipynb index 0a11f5f..19dcd82 100644 --- a/jupyter/Fig5-scatterplotOverdraw.ipynb +++ b/jupyter/Fig5-scatterplotOverdraw.ipynb @@ -90,7 +90,7 @@ "outputs": [], "source": [ "# Initialize color and plot settings\n", - "color = fss.plot.Color()\n", + "color = fss.Color()\n", "fss.plot.initialize(color)\n", "\n", "# Create a color palette for categories of chess openings\n",