From 9407f506ad0c6c6b1be01eec7fb9e99465c85612 Mon Sep 17 00:00:00 2001 From: moralapablo Date: Fri, 3 Nov 2023 03:30:21 +0100 Subject: [PATCH] Modified all tests to not depend on data generated in "auxiliar" vignettes. This allowed to delete said vignettes the 4 data examples stored that were not being used. To remplace this data in tests, helper-testing_data.R has been with 2 functions to generate data for tests. --- R/data.R | 13 - R/nn2poly_algorithm.R | 2 +- data/nn2poly_example0.rda | Bin 10782 -> 0 bytes data/nn2poly_example1.rda | Bin 11064 -> 0 bytes data/nn2poly_example2.rda | Bin 10856 -> 0 bytes data/nn2poly_example3.rda | Bin 27508 -> 0 bytes man/datasets.Rd | 32 - tests/testthat/helper-luz.R | 4 +- tests/testthat/helper-testing_data.R | 36 ++ tests/testthat/test-add_constraints.R | 15 +- tests/testthat/test-luz_constraint.R | 8 +- tests/testthat/test-nn2poly.R | 31 +- tests/testthat/test-nn2poly_algorithm.R | 8 +- tests/testthat/test-parameters.R | 2 +- tests/testthat/test-plot_n_important_coeffs.R | 16 +- ...st-plot_taylor_and_activation_potentials.R | 10 +- vignettes/source/nn2poly-00-data.Rmd.orig | 563 ------------------ vignettes/source/nn2poly-00-tests.Rmd.orig | 105 ---- 18 files changed, 87 insertions(+), 758 deletions(-) delete mode 100644 R/data.R delete mode 100644 data/nn2poly_example0.rda delete mode 100644 data/nn2poly_example1.rda delete mode 100644 data/nn2poly_example2.rda delete mode 100644 data/nn2poly_example3.rda delete mode 100644 man/datasets.Rd create mode 100644 tests/testthat/helper-testing_data.R delete mode 100644 vignettes/source/nn2poly-00-data.Rmd.orig delete mode 100644 vignettes/source/nn2poly-00-tests.Rmd.orig diff --git a/R/data.R b/R/data.R deleted file mode 100644 index ee3976c..0000000 --- a/R/data.R +++ /dev/null @@ -1,13 +0,0 @@ -#' Datasets -#' -#' @name datasets -"nn2poly_example0" - -#' @name datasets -"nn2poly_example1" - -#' @name datasets -"nn2poly_example2" - -#' @name datasets -"nn2poly_example3" diff --git a/R/nn2poly_algorithm.R b/R/nn2poly_algorithm.R index ee0f51f..efb4ec4 100644 --- a/R/nn2poly_algorithm.R +++ b/R/nn2poly_algorithm.R @@ -27,7 +27,7 @@ nn2poly_algorithm <- function(weights_list, all_partitions = NULL ) { - if (!check_weights_dimensions(object)) { + if (!check_weights_dimensions(weights_list)) { stop("The list of weights has incorrect dimensions. Please, check the right dimmensions in the documentation.", call. = FALSE diff --git a/data/nn2poly_example0.rda b/data/nn2poly_example0.rda deleted file mode 100644 index c258fbd6a929f7b19627beb8f0d3f308eebf3df3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10782 zcmV+(D&f^1iwFP!000002JM@7R8-Bj;JXQmm=z;}Sx{6IK@rqV5R51)m{5X96c7Oc zQAwgm1|_JVk_16=&YPS=(@lnkCW9!7f+z;2`qS^uyKm;b_1>EKYv!`nZ|$mmy6RNz z3VWYAhtmho@8UhrOQBFWDO^-4g_D~kDKq4icZx}fQ7Bv-BuAxiQDzajz{Et%^t#b4 z4IOJOV^brY9TW=3Vxni4Ui?=L6pnf9((sY;*WZ6t{=55dUNtZ#VlIK>ceQ`XU;k&- zb4>pyb#neU%Tj-rrTo<%Y_8XRM-uqOi6&@I%8orc!V0EPWER`z+Q|_84}Bjm_VwcX zN$tNY{bMf5f`8L(9`ozE7N$lw&Hsz~8Ab*sI$CD`rncWb8Q3oOYijQYV6lJuLJe?w zn)Umx|CQ?;fA{-;THtp%nLins|MqpZg*nbc)T#hE-UA6p8(gVyj%9--u15MDdR>^9 zX|^?4m;pUOZURxW{D6gr?4Jp(#>nUGo@cfQLpxWDh)A6!*S=v2H@a8VEvE>0X$oOTALHDzix9 z8uazNRgm(#1kDUTHx45N-?H%H>BRNtaga5J5Qd1~h@bPT>;+xR>6VtZc6M_Ke0|L(a-Em7>f!(inUGurY4;8)wdU4!y5c#DN>QNKw2JSrKIn0ZR z3)kKI<|vM)MN6Mod^LsQW!1}c_c=nopdsZ4zYjPUq^itRG{&rLR6)4@LQt^U{qbF*gwvO_NRlr?_cgf+UZ{1R7NNk zdq+Pi40;R2n%BTqY$*(H+1x5MtPMp05vOM7%|%_sjUE2FFQCz9p7_P!n|P#JLhziv z2PO@Ds+6*QhM8Bo=YiG>=t%j(lkWEd+n>2486>R6h|p8I^x=A}4e3@-h+G1d*&Kt} zwhhq7IEo`#Do~tpV$`rr2{H;Z1w~%3gQBn1PTZarP!r3o*eO><+V3qU`t$~LMe^o& z_$5F>-rBepqhC+& z$Nu6xC>k>HdG*ByOC{pf=GEMQdb$3EuKvT2;SA@Od|3jG$7~O(e4|3&r!bfHFSDT@ zy%(k@OhDi2hNG7Q+n{^=iF(hGWzg#Awr^g%3U(#3a!&H{L#8)aEwGY?US(cm)9kr0 z{CZ&Ks)9?{S{58w6}%WaIf_<#4%(beU?0csAZYw76Gp#6JL%lH{REc%tJuxe>4HnG zph4LqHRnMtc0HFil8JnP^fN~&kB*$hY(HO`AuyrczWRWRAZmSc42J%<|J*N@CaKoYQe^9HnQq+ zK5!?+V?pu$LAP`2P|m9-tF7z=<)*J%YwiePS^SF$sdopVXvCKOFs2kbIK))qXK%$u zJDs0e0!o;6`0Bkc*YtsIbAJ!bUJnbJ-cCVS1k@V|neZprWAUm8r||b?(9N^ZXPLqo zXfbukTyi288YJsQEx&JqM*h|^ECHZBKR2{0|0~op^$y2QL;)??Z{@v@@eukW_By3% z3I~$TUK<_Tjt#RccPY!aLi2`5pF9zN=&t(uMrz9>(m(Fvy&QNG>Vsx^_&vynZgsxI zOG{^B#m6Bb>tR*sb9=WgGI9!vxVGQ^ei`AF(xBJuj(E(axRq3`j73J}G5t5&A7Jym zfX)7XENqf<(&81J!iTvx#?H0 zNyif9)7&GV>)S`?^F6O1Z}qzncfJDXr*q4N%*uhR;}M;$`!7Msf-xVLcSArw>9k2& zbPZ&;no}e?)uDNdc<6KI_t3qMJD4-*66AM%;5+z%1%47m&wuiFfU2vH=Tq4ntawAa zH`i`AbVk*spUAj`>Fz$;x9n}j=J5lAr%@TRi+9@OyxRh0zpOeZS(DJ1HEPv+v>3`4 zsJ|_V--OM(H=bFprVRP1M*iz++OU03yu!=bahPwkR%wQV3)Jgb@TCo`fIek&57)|D zFf?;o)j59?I>k$RycYHYrul1S<<>jUq&Vl-3|S>i+#G!S=Me@b-aWo`iBdJR7>3OW zZ7PG_rX!bQb^#Vw3kNuKxMNgO{N8#1NWo68PMKzoLYaY2UC{XT5MZ043$q8 z^*k282NlDEnwSP-DxiF_D3~&{)HDcRexl*1C?G zp~q0KYg!Prc_k*a$b|8G0~F@Z*td0l1~N?M*fr*C#X`D(jp2I-th2p8b!O8dY>TvB z(fBL}D)ko|N^nhKkJi0Q2i80U+UEt#pHYL@?)};|{-!QId8QuGU9N*|k`c;_a1
  • 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 diff --git a/data/nn2poly_example1.rda b/data/nn2poly_example1.rda deleted file mode 100644 index 7078d15a20bbdd74f586c08917858ac0566ba6a0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11064 zcmV-8E63CyiwFP!000002JL%yP?XQpCoEtD6Q~F(n81JvyF>+B6j4D%z^sUXARv+j z5fKp-3FMe4>7K4< zHIz=!=A4+r#>U3M#>vjk#=$k+Wt*}4umn|#%Erb?nf}Gj#>qB&x?NyuN;Nk#vD4PS zqI1dIL|=l9jlw%U{?}^WzbUX$=KZxA@A4NEPIoZ#Ue#aZu>a_fzuR=aymNoGbyo2= z{%ZR!C$jzh`Hy`#&Kq5tZg{4@lz+(n-TwSd9uDYy{hM5uXkf@+ZTG7l;lJAF@kM`= z?XFtb_gBm8UDL-RPxxE84mjq`IWbLaCvRBQb@RW8{wprF1*BuoFflUK*RlM+ z9Q{pc-oNeNA9&05KY#vDo>Tre&;MSx^WPsk|F56_C0)u1C}UIcdppko+fZ>r>`W%U z_`vA2Qd@`>gI^-dKp*nD0(9HsW@5R=!(qkAH88q-v-6z!D%h-aN~p{E8#I(|o@uA8 zj4e{JyVK&|A!DhZQNUJPD0Nw?e|NnOHtlJwJ3>`~^v%UrMixxrKl^jz3r~fmj%+4a z7?HNMV8?8z>afpUVpoSRc-eCFMxB9?J@7*=QyzE8;anY+i60!7*OIW3Z0tVGLDFzgA!l>rx#*bx(klARy##>(l!?dcZUi!2kD=g8EUSDNpfCCOMuIh2U!Z;glL5+521d$UH3xAAZ&;>kO^u%2_sypt?xCQpv2AA|GsTI1V?NQ z4)T&m=BANfY|mEU%HA8RR|orJA%rmw6zZVoFEuyo(8oA@Brv7fZ!h*1#gyNvmVtq# z7c));Ekd6+U8&DbQ2-a;ocl$^3)>Cc4$)~}q3ws;h~Am2Q2)Mk&sCWS?3BLj*V;3I z)dknCF|=}_@2jAmy6z!pQIoDn`FaYA(l`{`vp+%8#vCD6KQ(A}sQWUNCJ3!IoOgsh z=0bqTQ?Y#$u@K-Zf6~>j6mu2?9bY%N66^r4b+_NGT`V_S0TJiZ}$*LK@j9qwv!OyFgHt#yL?&xsPrr&}nCN<}3ohuICQ(F0Y zAOcz}-W<0$L%|*)`OS*8Lzu^&Q}sT24)mYpZr#)525)}-^%(_s`H7!ZC+}k4>Ui;o z+`5=;)V_S9`%$pIt}AqHR0}(gZyWPi@cxOfQIMs`x1=sX2x1OM$E2HlhaTPfg4*pqB9mDvrsr`rp zvu&s6h)N~4;Mp0;y_cae-cCtgatAhzd^BNNErXVnXG_>#Hei2?$Cg3M#n`x`s_kGj zKjt;at6M&F#3HW7N~`^$FfIaPL*pBu-FUuEp{^j5EY)9iKcXB;9#*BYA5+5Sx|Mvv z0tGN!@0I7dK?{c}99m-4=R?Q&*WXl}6tSr;wr0(V1JG_hG1b+S0|OIdMXGP>A+56u z4E+M&=C;d6rCfI*W7nd^5*F{U&+2T7k zy!if9gao{tqyDv8))Dbl;;XDvM(7)~#`>PN5)2r=YOW8Q1MRzeG7TI zuym@R=<)tnz_`Tb{&cw#M)-Jo+gr3?O0DrqlRgcoQy%1wVeY`P$dd2jH;w{sRTiC~ zr9jvEpp1`-)Bc>fGD3A-Jk;@AzHMxA8fry%x$`@zL57`9j%Ps(`q>*Fn5B;){3kIkYx%~Y*|4GPsWYJk;R|Q2i-?y^&zCniR z&a#kN2KJ}!*ui_e2TJ9fy`O7lLyBx=Sxsmy=B(4_kP9t<>NmSXcMF#zaxm@{`DtLy z@i|6Hc~zJv_1a%iA{^?uTF%wn-Hl8ozWoEzYFK^F_xTA^OK24kP<=bw1$(VGZeOiC z1Do&gIVxMWLPn$T+1ob-Ayx6#`J$2(j5)DBZSC7#SgEBsq%b-Quj4+3L31MXSz3p; zo}7-GV$0u4Zw|+(U{!moh1)P)fX}~^*9!;oj676rx^PHqyq@tn1-k7o-}bT8gsStJ zXFG$;u&nDX$h-4Hql?$mhMNT#YVTy{=97a@^U`_Pb#fp}M58c#44`?*Rj1j7_K=@7 zCXj5d35~N0Lu8p6&^PID{fnCm7Kw_Q?hLhu#4mOBncHkIOlQlTHTCsSFSN7W1eLH# ztZ?frOE!oYbe7*f^#;o-s;>KsFU2Bn$3DIB9PDe>9w>Agf>3%pU-TQjTCE$13R|6qc-p3pIj&E_|et3L~V=Dr(Tgy>jod~T!Gx98 zEE$?Dl*D2`sY0Ww4!e}v3aDbY|6rH84G-kIS1mCHJLG!y z_#E8;eH&M*iCpQ0_Msb>@%WanCJSp?EG@53v*{aI9G+uQKM&z^5vni z^AhZ>hBiN`vTQ*0`Gm^-NTNoM!Svj zB3M81vi91NKpa%x)b_wE15K#XI=d6DqtpF@x8AL5Fj><2d}L+b z#*AAKpPad03$;Ekj-NhA#evlGybqu5 zf*zp<3(ad(Ao<~Zv1K;w*iz+n`KX&2j^wT%{QOM<(r-%jtX^=Od|=4_oweqxE_eD^fxVx#4pf(cih#o&j1@eG{B_j8jc)vO!9f0i;Q)a zY9i+ zQ>>Hzwh4=@bMvl8xIs#9*uvzVSj^QPOs=v!4%5(WdZbtqX^S+RjD#wopnrgSD%O+v1oSvj?q}{daMZZwy~vmtwl}`Exh2sE86RHnz4OHb8q5u7Nk`8?qobz% zc|j0;@y1y$>BIm(B@ei z`8^Ht=lO2o86Lo<(fwit)}r|0aQXH7sZCh6|IqN3n)TRL(mA%IG8seD7MWP{TVOt? z2mRfaPAp$NwKB9%63VVw=WD)ULiK^w^QyN`=jrU}ddp-MVQBii+~qv0q3G&|qpMuG zFsX4wXL({KHi*2c9z33p59UrDg=<%#ZQByJ0%jjHJ)aQV(UgZw?Jpl(xAQ~tbIFSd z=XB9K)P#AcyahWO=T&6!UBrxnr8`CUOTvIi&DqMLKFn0|@ZKi=0tX+c_AXhq9hv1} zB36c+=-2%CRee`DWYlMVl&tuPLoFqbDEj%>acZOf^@`)j=rc`C3A+JJhil$w(nMk4 zXoQaDB@U=M8O{4q#uZAfl+}c6RWZxOuu`aR9ID^_;+)-Lk99sKO$k5gSfvtpz&rE@ zq$xXaIr9wzeQAr;xB2sNbmRIDs=MYQbKus8>L)Q6=98voo_ZMaZ_or($G>Bad8pD4 z9Zu|7vyWcKua6F0)P-WSI931ttdo8wS%vvRI`EDg)~3r@RT+XOy(y)6dem*J*| z?gE3pbvW{46aVY^Fpb;KE*_ZThDyD$cTMp}pgmeR^5nT2Nca9y>+9!&DN1)=B=Al_ z^N66czM&arC2fi8%Ug&{{t3C|p1zr%ur>BUt87j!hN_zhgir98qTg&WbAr`!v zaX)qAY3z4o>Z8KCK1a+vY`ddAmK~6QJ=BRiM`cE# zLtH=PeUA;;Ej{;cg<2<;U~G;-WG<%q?&nZQPJ>e0{ao}LO_)-BcWp{1AGT&r-GW8W zfWBzJ)UzoA=~c~7!dp*ck5+@q{*Y2^h`cJkZN+A!%im*s%^rj-^LAP0oL+q4bUW$e z-D0fVx_@iVg}qRi(=6-QT8R0N=jI38c!g~o7Mej8H=*TFN}~K63jULCPr%@#HU|pD z8cMQ!yY8P{3_TCjSB8Jv2QBO|SELlpu_vhaSj*Bh99Y>R+Bx-Dd|SX9Lv|D`U?JN zW5Z?S8d!#LZz|6vnQumY-@_R#Vx?g1qje=VTmZUvj;r((zlTbv(WP=43n9y%>U?3B zHguUh6G@n7h75~aX<^=RP?dbBB8J}|Zdc#b<19ye7UbbhC=&eBTv*xj( z_PRp9^8`nk!V@Uu_i^;2Cn4UIw~lGMjrrY!U1|Mvtln^xe_U@DpcwtE_Ogdq5o8j+ z&NUmEmA85Kb}L~^<5#}AFLR-8ZhLQ7U=F0jlkcighll4fZeVS{p8GEI0O*LC43$}+iRrS53$S+9^u2O>iuj-^ z_W12I6qMc!trpeR3zp8pfn{bU@8dJEPnYKB=i(2Q+t&_?N!=YC&CD80M~Z{^6Zffw`U*o(}t0Laj>1zPuDec(O!?t}`x({i4hK zSB$KI5~lQn$=j>3-{Z)g5}#2V_!#n{nVt>Jb1R;fEN;cFzIx-2=?ySE@ad?_2`T9L zC3sNVRT)NC42OI=vk59j!kyYzPGLXqrhD7?tcc~m#! z0TfJb5xQzRoga(uY;ODd2D<4C%@0$8*tpYnhnoQd(vw%66y(msrf(s$k3KTP)*Fr6 zJZ@w|jp(5uVews9U)A~fKzA@YI*A)e4()&tmF%w}b_K|IceH~#vD2`ScG32}ldv5JroRf1rEG(nsgl^_JeqBX5L8X+zjLPmr>Bv`~GXarpu7BQ+E zAx|2MM;Su0G?ru~>$gM5mlC;K&YHb(lenj8cR16!hEQNIH;0@8VQX_5N;zuuq#0$*k$LYg=up(v{KZweF{5?`c)v9wEUAVCHh z;unjn$Q9X{0Qu!N{O=sLnxo5P=YJM!6ZoLMI-q;ONMfUQxMoflO%kNWb}kr z$r1KTGBi070cjS8Bw-L|ktMk>A#IjHP*}pC5a3NE99V*cxKbpzAsGaTLjprca6(>2 zFhdxZG~vPoe6tQqVJVhEB~HciT8cEu{eGX1oxnO0;1jwe+=0eIUJA+eNHYl+U@3}F zKb7!u3274Q62g%qbV5>(G_e(HS9U@QQY7}p2~Jt3Bg|Kvz+6)3WuY5|WQdX^`lN`@ zIw_5$B|`g>#QBLqmPt_v$fc3a#F|QxBzmO4OL(#*;WMNz$*WnA%TDN?3<@MOBl7CI6p~hmB#OqOP9Xl~8eBrG7MIxI<&G6GhYLa3YwDl|g-667FHN_tql5}}TSz2c;}ObC@^)C4Can?*w5rc*WmcMYbA!*Ub}=T+Z2v{D|R=``Em~FayRDI4t&DaARWrQ zs9H$5;rl#W=RL%CRymKJsG7c9R<@3w#6KQR}3!Ot)ozsQ3uxUN8QYx%ND?jj{RmdF{p|jedjW@${frd@Jn4P zsSbT!d1iqh58%+TE4OvL?jysRxrF_+3EKLOaJw!Zg*q|Dw$Dr7K%w}<*HihjnEF=s zdt&xDb|`VV&r#6E+^LhT2}?d=x!p0vnO%>d;iboMo)}T6tYqIQm0*VSBq!Oh4nw4? zEx*^?*^4Fe0shI{-ynfk?qz4A09L5B$2nP7LZ80tt;woMNLv&%?y%wlG(FfO{C4y! zCdEA|9=W|2bG~o)D37Gzr~?;sU=}~rUQ1lHdUhiOhI&WIJr>0WpW`LgY0So8gGA$r z@-A$Zr}uw#TZ-Kk4we-=OEJIaG-v*~W7zn0cW=ZnXkE8l{H_XPKE=W|EqR{0F$2fSGAJ~a}3+8?SZb8`i)Hp7U#_L^HK&p_*U zEtmc37EtXh-21^T87qvBh1^Q7fVOeIb;(CQV)d6ichQ~c7`N!|vbCTL)k!I%AujpA zkh7k%TWAo+wf5E?zEF&fd}lKogR`+<;kWyA+hizE-St_kAse#R8m?UU{4M7B9Ox?u z7=nsxVS2Ld0JZP;wI{0RL%(xIkap!ONVyhn@5b1G)#uCYKij52%h2;;$s5{O31N8+ zxt`GcVRd|P_$w?o>zA1^t^xJ?oF>=~zQvr&Jrqa!7pR;m`y$Mz98lEkRO2$91HpzizOSQx9th+pg?pe^=Cv?s;>IY`O z^F8yeNgd1FL!wjGzQ%;}LSoDGqM+olPWg&XgsOvcXg_?;WBFI=uFpj}&@#E%OOh6j z70oAghVQgtkM40DcE3HKzI~No_hxSF5PI(-@#YlNYid@0jt;;PW3LBSy#+9Erk^i$ zw>U6jep>C9*T;yDNeh#>Ly*3sdldwjLgO!sc^!uF|GxCZ27^+o_xbT56sS*##42h* zPn7?n2VeI=Tju7ZcDqR|Z7p&?y{QfR6hB)0;BLU|?3b}Od<(GoUay{~Y!9wQ=$c{;`; zyLVbcU+*O;Go~`$FnsQu-xLI``|g+sN769v=)@VS!ywpJSk67SMH3R@P39VHtwFD6 z91c%AD1b4_hHvR7Fja`bEwNxfbm|{_&Ks8mH3y2fta2TON-L#Yfn~1H)BG^ArBe`V zG=p{L)5oBA*)fwB9P2TEZl{xa-)*c&d}Pab!oZUEBP$kk&w`M5JSLH%n_$p1l)aTM z3HV7cRCn(jEOgE^AB%i|S@y;zfgLw6eQlZ6_sUBUnHjjc$2|)xuAGW_A6bYE!ACfK zPYYs4rk~fQp#@NuJzKZ_rV$i=a{lSOYW44z-7w&ivCD0KJ7}{XPL?V=ik{!Ng)`Ua zVAApknOnDf@x?Z^XM!a<(B-qvz_xE4GG|sHv_SigeSDl&2cd6O z-?*+aC$taUo3okoDrS9FwTK-tgZ}1>xb-U3-w}P#1KK;|G*=1w?tJJ%p&ok9)qAv18-1mk0NKUJdopcdYNX z(y;RuXEv{KKl&`UWAhHuL#-HJwoaE`=&;!1u;g$M#B88+F4aARUAu+vDV|P&;tb)? zj~ivNZ>PGI?4diz^pUI)>wW?4$pI@~9CJj*kz_yj$uJn!JM#Q?|03w#(`0`1_5v6k zwACpd5`x@rvEt=>O|kiT*`kvXfzVoW_+^y(6vRCI%p)_Q0k5d5mqfUkL5=tEJ1Rd% zv2JI1NB?YX=(k{;2naZYWuSj;iR4v?pA$2>dQ&Dgrfxcbs=ios-FdT}{6?Tx>z>-x z{S)aYm)YbTRKZ}~p&r|E9?baERB~wOAU66APpJMWF`hSYa zzg79CnEa=h{9C_&ipebb{QoT`|9%sO{UjUl=eqL{KXv?GRGB-p4^J&WQ+O9$`D_o& zi8%`~p0A{ta?c^_VabMBw{&rINaU7f?joq-f7u^x`vA(q^gF6K^dS4frmgV}U6`^h z{+z4uOQ_N@3~thj!D{Nz{IKT@aHnDdPyU>Vn6Sg(>CNp}Au9DFI9d=h@5jGtu!z7K z=evrhBI}^vi+SmWjWPNTy2)1G-33)KCZ>^^x>(B3xs3ZKLdMQ*8$A@CV+?2J$B@8h zkhY%5rLvU@!Fh>?6Mz1|$THPI^)<2BKe^}m6jd4;o*&^@x3B_=V@qmZBnsmb#;@IH zefMDn|H3Q5q7zu1Xa896Pu6RV39J8O4k>E>ZGW(pW6|O>{Xn9t(Dj&^3mL>!JLY^yg#U z*xMc4m(ww3rENB@j=>tSnU%4;H4r)P;mDEs++b%b>~-Nh4|Z72e|sZF8yl8oRNT$u zf~G*l@H0v4uy}im#3jG)nBzLuQBdp#Jukf?a*iLtQob<5HywdU?=Qb>=Vbu{zf@mt zv%Z2kPiOp;KXU?_`@Xd*Q?5a>@7L;g-}Yc-=#$x$hdwxXsJ?!lt1)C)$=Ta}t%9Ug z#mS4)9kARZs6L`EnD?8aB9U3I2qt&^7l|k2(OODa-uiR2ODPHVjXi z=|KM;o2?%HYoTn1UWk8aBQnfKmlkS%#SZ%x`_n4#k$G~zfOdf+K``X zcD^$r3F;i!jS6ULMtiA5p@L#Dk)7*Pi#THi;yBQ=`uttBjTon94W6MqJ=mq*CxUpk-t+(mto>cNhRQ(O58T6 z#EGe-T8$(riy_^tNpY4SCQV9-iI7ja@ssbO#1^DG7ZLQRL{dSMASDe%PD7}hMjVqy zXp=@IMQCCIaWh5%wnER3??1KnxnuoiBRzkfSIFpb z^el5*gvCc2olD;8L%qV9#L2h&p)OSBXlG9jWOENMU2d}&66f7LB$IR($`)w|r-@EM zm?_MmKCOTdwaOLNZJ)5@)agEH z1qbRpX){C;Fi-u`PcQW^&?6IM!8Q08nd@YjtrG)K8rE=qm4OH_Itt{{a164)ji2%F zSq94>nhnxuW+rVNpMylR)kj%<}T}$g>;3ic^JK z107YdjfW9@_lYR99q=>WwD$ybt0)U3PP%~0s<|grwjRL_1${26+z(aQ?wrI~zS(Gse zoy~GSMVod&GYq#XX}I9vG7HlXmkMOw^UjYj^2fok4=3jp>0s0Bi7m@Hsxg!Eu9nQc zEl_in>qXB|U2s{e#2saI73o*vpS_>qh{+>1M%hu^SWs~|W1~SXj8+A7d22Lbf8yKA zDT1;1DpoJ=6PF~u*nP-JxJD8Cn>Wi|>m0*u%QlX4ua;q3_@*>7^-O3sEffp?sE?(M zrs=cXK0-IoY5w38Cx}UkY4~!I6Pxtn<=*Rw;^3Oq4l-dLr*kIv5 zYuk7>c3JA`H;;QFQ#>|ntNmxBYZb3(;r*VZm)Nl`!@RFe1EWrtDJg7HhlVYi_YY_}Vz(5p&;qWR*sY^eFR(%o z(wB1{yu+gp?cNQ?@-HtzoLm@wOyD{e4xP)l-MShIwFYKBUp|FnjZeL@=f^^IfxJh^ zi(8PKd(+~~o>H{V!S5f2A7jZmKHhgT=R=8$>NC|r7i6gYWGduOV1)7ephpYDuu_&k z{7A|ZM{Z%|Y=@7BdXu1~&?SX;Ko%<; zy-W%od0^)3x~FloZNPh2xAu+BH?$XA=bqx&i@DbXW--hr5bvt?JQq{LVc+x_o5o(l z-gTzA3%0EX{5*84hWZmzuNpr2_M#7~((jLN*yw=`YMEa+e7|Brj*-e48#incsN`v# zsSa(y*F1y+nAl^LXOXgK2$@+&PZtVWVw38IJGPx+IFUbP7dCSX);#}WC*ZUf!{!gp z&KX>dovHp@+f#M$!Jx#4CH@<+Svfazv3?AOH?8U`Q#Qo%7e9-w9s03Q=48Bxuml$F zN_!H{6Nk+nLT8W6aKlQmCH4xY8qj&=)9bu*Ul0#{(ERCEfrX8oIl_S^z`Ua2Q5J9x zYiGO|ln9hZ`ckC@UGZHo_%unkP<9!jz0#HVulkV0IXB-u&J`+G$6j&R{g_Tqy3NN*~ z*B61Y!~7-+Z#$s_T^5J40hAOk?-6hxhpb4pNwvmV(5&8U@rtH_&kWC)uQJ~YrL;41 zc|UIh`pIiK>aRz!o~>l-wYllQ)OIxoI0Vm`?VFX~@L(NHRk5(K0=xVpx+QoOulsQB$GBFV|y=inu zL&sXn*wjdeT<2Iy^z710|Eht)v4C9~g0{u5NCF$AezGN0oX`tl%hLEPcJczs@)nR0~?mBjLC33g^%D)|V{;T>Vp-LHc zK4r)z4Z82yWxhJm1no&3 zm(Klt>I)ZgV~{$ynSkFT>W%yAK- z*96M(9!f;o&}xMXEE_C!Gt%$W>&B!kv+XIu4CoDZ7l@wY4=g-l|6FJ-M!o3pI=4+2 zI=Es*MCvUe-$uKOZz2}T*Z$z|>i2-g{`Ce=HgaKMm*Ty`%Yu-2dGd(jj5E*<3jElm zUxfpalfF5;pP=5XeV?Q`1L(5XnZ*(}puhK>f|UOiXkqvx{}c!I7`R`YUMUY1S9iAs z2|a>v=jrQ8D;r^Wr1tdeTT@u-?{Q>2kP3|K6R%Iq3534Jw38|J{Lm~hpCi2{2)Y$F z-`J~i76y}_R~M|^51l#Z_4}e4q5V$RLE&3!Q1yAw>8{O65W0xZ>co&B)STkovX-I= zN#WBiqu<+LK$cIZhnsNe;WrryH31s+>d!_#wVxK27#qehOuRP zA?==J?Gv9Fpg)xu8L|pSCZ)14V{sWY^PcuN^fVF6k9INV1jr(KY?#n=G=jQY{7-zB zn?l*5Pv<+9-iE$kn7-qI2(&4FaU8zu2K6f0o`-M{hO;cL9UMCitVIE9Kd&&v8e?I% z-la8Y-ZOeL#!DE}-)2Ykm^&fMN$6)}OgdC@aBV!IxdxaIE~}XpJb>Jb>CM--*+Ji2 zhS)NDZ)gfj?R~dyKX#-Ac($euK!wv-zu#;Ds9(8o@1YMG5P07Io_qQ#?0K{2hVLzY zsPq%ii|3w)$S;-HfSOQ0c<(XKQC>`1yy3xjM{zVQUjCx;n<#X|f~OuY>u)m2AAX3j|{TD6>e z?H5^KiXM&MHhBSh9L59bd<&p|y(?4Px*QV&i+((wU_yb&p1Pb}c&tW3@PfW4CJ%qElCph{S=V|NfYwXsO#RA};r|jlp1UR+ zB(BBCurs>!kp`>_?NLvRS_V})978#_jnL0Hj-%NsP?C9S%&=VvGK;bVMc!=txK@#cE^CqiQW`uJ9(-%#AXU13_i32S$CnXJ4d2dtOg z3PLBmp#PeTMuT?S1jY!9n^r$YbdaMzBnbD;r!7H1?*LjT&v<5z>)p=aW$dhf9n(B|lVU_pWk zb|`ocS>FW^neJ!YkNT9uia?vJ|>FidTD$*g$up?BN09 z85n4EQ2wqa3|(i;PKt#KV30smPMQ944BrsGd!_n$sQFCj*<417o#5p}I{+*|=W_cPmdK4ZKuO9@us5Mud{4*Hz@_13dWeF6TnSPOU>O_xK z-Ravmtb#`0)|X+0G^`ehU%6(V4rZE{KDvJIAvBbBHtd`22+d2S7Z%S9LUq;iX%44B zOqKeu{D(|A)V9aVP=@Lt`P13MkD6kkQQ0#s_fZ~pzmPVPiF$oZ!D!GsOvD#(0xm~XbT29Rq-}F`xstzbg_n%-uQ&nln zQS{tBi51Y^ayq7eV-7UzJ7~DOyArFrEb`3y)Uhj4 z$7zo7YNWO1JvcD=1{*AcX9u3%2PNAr&KwF=MXO65ER(qm3@mwNtynG#p#f6nT|0xZ zeEx;m->lgCp!UJ9@vop$Zg5U+=UwQF2<9-@J{NkH^W666bpZN(hQe(|I=)%$o%X~2 zAr@^rxYT#a3ZUN$FTP+QkF}aoH@@tq0bROIHP&kw>JPS5*-qs{*AHsjQcDUpNyi=i z7`hQ#O==DIuJ6J`hqNnRHlE<0zI>(K`dsLJR+1u{#Dn>lKj$R`{D!WbrE*FNHB zsb6BJFgAU6k~U9#jBS~9VB%`@>K?YD;&CErU)DF_nb5+p)<`=a-g%5~d%${^08keW2Ss+()z5!@}lw(-0mB z4MsvH{E7BhvL@0g;)5CV@GSOSp>PgbORJI;~dL9%JOZ{vMI_pUnBr}s=vLJ z+BSvsPkVT;2Hl2+;5nZDj|!kioiFLi^4VDVX;{d5L>2no-*1SDnucPoop*m+MR=_= zsSYk)rso8_FectxktCGXY**Q6XYtxSFxu`vpg z6b>BN-ZGA99L)7MxtBu896kQM$5Sx*M3Q{EM+wn&SvgPb;VibR(>v}_X(d*S>6dJb@ha0Xw2g6@xe zhd;8wU!wTMFaAzYb@TOlCYy_uZ)p$a+wFy}==zLPnO88w!*}Pl{cYGXacJl)Dq~K` zZkycq+o1fnRo4`23YxOVton|ZK*b{Ucclqiux0P&b1T)9p&-pDU_)&?cI-<~cr`a3 z3yjt)&2n&s20aVD^ublouWat=R&@u4XV0iQ7i>YN1WC^~!v4TCf1|A2b`P2r=lz}~ ztAt5gL+<`M#=xZeC$}$Cs)1I+@Ofd)<}u>Dz>*r_K!;8bj80D2f8gsnXzg_1 zew;rGI+{;X8}9UC>T+9)9qUG*>e-UsC*lvFa>TEG@wXmq3*~f@3UnYcYi1_;Lax`>Y-17Qqu@k;}YGJc+)*&od$NzATb11Sp1%mCPII%k*s0rwj^YRG-1e}3Xz604y=@gx8GQ;gyG!rq_#ed9d&2|6 z+C}(x97u(B4GxFyU%J@s@q7N#hIs7p%IR6XK^l|FOWS;QwqktK{cY-DZqU2=?w;i2 zF>E&-l%Mxe9s77%ckJz?VY8G-LX~GNGS2iHf~_6Wd$fzw2lTOYYed}07I)~02$)~? z)*2SmK)gyZrk zAHz4=T{-{W6>?RRZdRmo0Bd{WMe(>zSlvlIv;Jr#wrn0NIGFYbo37{vqU4JU(N&$P*j&YV;T6YGc<1KS{OcTaiAv;EU0oZAer1k^ELEhy!$yT@l?? zSf$bNDeA-~c$`qm+)_D6;-@I}+MszjpztQqav>lqt#Fy!#6=j3M!RnjL*x zCA6e_>bDMGMwUu9&(JeYpx3I$Cb1f@d1^znj@K}sg7ABGqB{RW>tZj2QtIf=%1Fo0gb7OMwEmVkUl$r_B%id+hiBCg-dGU(ERT7 zUzL1FdlqKA&U_v83_G6|hH(hy)5_+3NrgW1yoD0Wz|C*$`?0($d~w5-6+5Z##i}mQKllVIwYuI1 zQ$^s?t7M(42HOA+923{R`w`wQ6K-uh!v)2$ixpCO<)GsJd()elQ+V^p@u<($myy0B zS<1&S0-0O8^hHip08_{Q0=3)?+I-(_w$V<;s`Ys@7VdV~uh*cvL&+ZsmFJ{i*m4cZ z6ApE5e-sRZGapI}B+4*3HnU}H3ZdA$Xu5dYI96EvNTn?NjgfL^h4yFUpM+;MyS0@eLJO=$?P-N&OeO6{Ab_T2L*-JIWR{qKA@j@DSZSxV%Nqvd&GJ(ns zt41KiW6`drc0PZ>+@F>rNS!@D}5#2-O&4mnf`*e2UGK0B7as}VT?yr z>tIjsnzO2aH;;Wv52S0C>(VSS_)85;3wW)CzyWhF?#vC&2<(ValkR&26nx|oY60F)`PLwQ{%GlruiI*>r`y5*NMlN z^KZ(f_kG5`-rnYIa|JM>zJn>Vz8C91N8i#-e~#^o<+zU=eFcTJLeq`6n<2I6nEzf& zE9_Z&KCWYM6wQ8@Ut9S|09*=RZK8X7B7^2svmk6O6v|s$KZ$#aJ!;2=I=Qbv@fwcV zh0dH1a)#@OJhKCPMd+?Ojn<(Dl)USe^1$q@iHPNj!cfnBd8bDAS4>|!y^PPl6&qqK zzN-#Vpzd|^`xkkiAuqDdUSk;rTQ96U)DPbvV-I6o`QBS-tdrk`Pr4xg?or>?eoZXV zP>bN+w+a|iDaH%m7C@Wbi`5rT_(97v!{HHO8R&ZG{?JoE75h)SgvnX>0F7&1yQYXa zhW)N+w8@}j$=e!wtL!D>7j=V770I~oi#w5gqXTFfwvP|zDPTv9q}kL)Fj9~W!_RQ#lbK4$+!K`C zziuUz%`jGtZn=g2R$V@wj7c06q?x`xk%gT#Ra6fCf{FWSqWA9Z!G`Uv zk$!TAKqZautoOt+=oYO}eR$|GWQqqm+7CU3e%Hc{?gjE#CFixQ;Mi7Z-Q(?$TzdvP z3q=;jdm3R{-vxhf`U_}m`4kySQGtSsucNzqenPM7m6~m3Qqc4?;jx35GSrTzD;FmTxDRs_y?zYk9C;Y|4~hU#~SRoEzxfoBn^7!5L;SyE;&>51=_T&{KJQvv4~$=-sbFO z2;O@|wqt%Y3~9^A)uk50lMb=F1!-p?zbkUy{nZMX{X;c!ao!#1REYlw9C^?pTz*k^ z#{ky7d%^21whQWvTy^q}^FoEk>C`MmAqcDEzt?zK6&hlE^7(?+VQ7NX5~jEYJoxs5 zF`5lHROqDCrm`Gan&N#vV*3B%Ng#Fm-|}A$FL|yT7@KGr>zMyJmt$WW`y>DHn}yeP zbal+kbgpZdTbLP`=>4b5T-UVBb^hq)|2b@2^yk3wkM6Hq6R37Xsu4;FJtV(}$RWZb z!WzN@f+FD}!Gd5y*i3j!xJF=~M{XtflCsJ~4ikOf%k<0g@33AYKeNS=L0+DSN0;3qnE z8@PxxB=RwlwggMU6~YCgOCa(bk@pGg_B|U zwkIiR$UYAHFk+&#+uNijxpOCx{<*&6wWv>A;mniuJVowU0*VKIkGWV%ue5mX- zwt?vTi6rAsWv?-I|H??3%oQqoowCpTtqH`=lu@FSBsh_DA0dSxNO(nb_5?E5DOp64 zHAiLlc|U>79roI$lD<-G2zew;<{p*IK`OBi^#swe=W7gsT`zk~#Ry~#QK|{OBu(Zp zmAzir`$Zc`lkuT?k#svDguuQx=`V%YgUY^#3z6pu?EACV4(T(+ndFU#WRDMfo^_Et zdo8kU#~uq6l4s9FQkGIhqzsXjgfK!AA&%(C82|MOqL8HT5cz@-Ng(T#%HE5}8u;g4 z#{T>L_c)NT`FqdfIKTU!DKW}FU(8UqgR7=TY}Za5Y}MHMwC<88HoTq8UhcC4;|?l! z_AR&xJ%_)p`o$Lh4r_docAwP=^#1s6nZ#?ra7$f1#N>m% z7%qp&&2;G4Sg{o^$Ymc#|Gy%vO+ z&63knue=MLN7M|LG=ySGoUgi{@-nF3+gv8I?;y5~+{r#XHvsE0N3@(xu0ngQe}nA$ z?fCAuv(m8^Au23WALPfa@yawFnjjYBas7IdF=lfQtSJ6vM5?ofeoJXg-x zj~`n(D?7W!d$D}i^yNjKd!UBabTYhi2xvVU{SF!UK>wKS>62C=&?Z$yxpZ&_O41gk z^oCu4p+jQ#HFrb;Yn7ycj(-$3o(Y`s?Q_K9h9Af4oMJHd?fa6gCC{+OW6$00utiWK zy4ccONDewupG4-xorR)V895_x6}s&>Zfj0CLrY{s%FLd{*d3ev^3=;$Q1dzUul$o+uIITrm_1G5no2fALd z#4t26ZNGNm3djoH?_A$OfrKB!+x_SJgOB1YdqcIw*kd_h;kjuP27VseT~PiF@TAg| zu=-D^qxRCZ8?7N}+*&ANPd8*5DOdlXKZ5q}g~s8Bcfo*-Yl#}m5{BG<6;ZDr$CQe6 z(AxEHp0^Q#ZGTo_!CGFEMk4@~9_in=;qI%kc312_F~`Qxr5V+r6+pBN|v+`hV=;DaAJat~qqBL9BN@TFhzj znuI??vi^#SFs5!cwe(Udl-yQ`e<13HC5*V-#i~bvflRq>!L3-DxI&@o;wmiNXT9=J ziVPNb4GP_g<+m^e8aZS)Lc7Lm>I% zpzi|jWT=gfO8mAw4I9oge;>J)0?joixel*<14B0A`nGMmq2UKa#(i~xx;(?j?@H)U zQm=RRQ4k5EgHBHO=Z!&K_^tyV^EbisPvZ(H-z|Z$@p#4rEf@N)8Y|g;bAxIj5`WG+ z0R6gQwBw_O&=(gykv@DGnEjG_neyv#;Dyn^ic&-Lx1Mg(9@K{ZjEjm3oCILZ`1N5f z$_8Y)-7MDmS^*u~zxptKw?lKlCZ-#Y0}N(v-Jr868af8uV>FnDF#3$`&q;$UOb?qi ze>}MnYE&K<-aeC#jJH=FKF#ZZhW;4?^Qsu=IGj7WO7%6SZrgvK-pz~M-w(U%OF9F? zZ(rEt!ksV@5x_ieycY_WeEhg!{&w(`!zc}5okI;N79*^3uX7s{V$aJV16n0^O$iLpzjJ3rE)jH6Etmac=`;=MM}pl z!tY|Qp}KgN?ILV$b6NM0M+J)#kJ&T{hT%!-UW>Vt-(ld}k-lV;6WH!I!{V3Tj7>}C zCGYGn1Dav8*V*XPQ2B_{>hS0~Xu3B+`K)vv8c+TlR-btSZ8>&c)ys;2`B5eCyu}Y- z9k(7CSuqB+J2(%qYU+?Ku-mUr^c6DgIJJLQUcshodnH9htB~<*hsk_>3#fQ`e`-^x z6sB7psn~zQ8Z)1J{JL~B1X2?^22@<_kv6Y(+;*h|mffFyp7(?fdCZD@u;NV{^v!nd zDs4)E{=@Sa7rYljZJ9)6)=f#w?UfD+I~I>Q^VVK}p_u`+cHa3DJHnBE@<`+9Lsn2V zGiDxLb^>bGz4oZ8C z?4$xFbLrYw9CL(*En9C*Z#KqCiKgZWd2c8?Bi0qz!NeMAfs>udrO@x*hVv>b;tpbwt)=(7Q$>IBu z?q%oH3$WGCCBNEuE40n=&#*gP4?R_`k_kSp$n1RPy?x7RsNH(azdIxn+Iu)gV`Elf z-Gh1NLf7S?*IVu72hCBaI9Je=H}?ownk!w5R=32u(0gI~-HWl^Ep6A~cW1CC{>=W} zO$_Xgj@j%T77veK@uj(%4ndQ|{u zs17+p$5_DeQwKJpO2)wj^Us`tA(6h(`Rh3$*JbPz{{?F(6YI7&RR09E$3v2=%{n1@ z8INbmv@sz^A8m*_1O5}M{R1xT1S7ZR(pfx3NZYvVKF{F+ z=spoznG*UDQ(_CN+@)%;*Z=m?SBAD&_$2)M8$UxR^XZ&*YrZ=)U)^HO*AWjj3k7y2 zcd8;QIlq>rUcrq2S_}itO zAwz;#9k~8?iC{BS?A!Wb|O;f;%J=+3XUmwAib(6d~jlZzwlC$u>=R(kU#BY%q zrvSu=t87i|^?)S5>(o-)WmvEyRWM?0DHd!IQQN(+11f)b9ID*$40^+(SFg_thP3Xg z_ch%&fD!tz=V|&Xtdg2_E$HwU5+l^2Fgr_OHcae{iQP`Q24U$IqPe*X{Ruxe@?osT~o z#qc{aio@mv+wsdb5ucVd(2@WfbJB9^+uiFddj13K;D8yDk2O#B$HqV)VGl;`cd zarxjjY&;SDc+JRrWT}Z8SxV2v7InAPG75Ik&7F8o)|ouu@o+3_H&cKbqp52Gv_9y# zB%{A<^&RNdKWkwxI~%fY>|LQ$)&=x+;&V0{(V_KjNAR@h6)YW2p6Sz!2cIer-Y43+ z(7ASDrEqpOFv@zfTZ7fGmQ%Isy+9@O880}#OTZ6uXzNuT+dqWvJjth@9E;$Ebdc%L zN~u5Z&nYl$Ao*r@X#g}BdzV#rDP!#;?qW`@U~Iguc)>(d5ZXLrMU6F2U~#R=@w0sm z(6nvSed=f=H1JA4cMh>951&6Q04CwDk=CtZ`}Rxkj7e)NFEFGe(xmTdf*IQ*8eNu6Lb=VSw~lc}WWL0i zm1P@4ukv1weNM}vlo5G9e1qQqaM%#b5QX7vzFJb+8=++i|m<64~S_YYFU) zk?la(4v6g}i8G=QCqQ8zF0nU#vJq0GDSv;iDo-GR1BJbrog@&4L?Igxg&j1o9XosD zVLMe41W?!;2Roo)J973W=0or!1P}rVF9}hEXhISpnUG3IBV-VA2}md+)Dma}I-!-o zA`BAV5!j>tg)l+*O87?jPM9YAB>ei@CT#Oii6f-40|{aaDmy44K^2v3>{Mb0D%)9+ z;E76{9F+taRJNlg{ic#&h)MzxD(O3wI8Z9-HqWiZfjHniS~fy>k4*fjdgPxh(^Hkst6sh{VDQR+pm?AZ^1RV|wMRq_o) zuI0I}<-7=b+|GKxJbW3NKW9gXj{m^q9iys-X_p}FneMAwqNdo(F@EZ>*%d5Tdt@PE z(*g8}-3NSDctX=l>WyD6M=_=B`>;x8F*59Het3r3W1h3Z3Zn-a(AYZkyG1kv@@{p0 zU4CmW2DGQSR}c82O^&EWxm6ejM?F;gb}1He47Fmsjs`%tPN_^}pC07)Pb{Bp=?87a zn}xj-w`0i#mwSi%)iLp`Tk^QfBy@Y_kL9lnfv(p)jIqnoFe0BJ`|IIC=)bn4%fa;& z(qu$ZwU!4#-Q=1*CvFJB(3En}rRZXy?O(Q+<4X@RW<3c}GVX%hQ8A{N=xR*A_w|Y? z-$G!$-Ry3YbPWqfex6u9umzj89pGEoei0Zg{=cpSx20Aa*DP(ZdBU^RbTAp~b56$BH+2BhF7)Atlg`k$S#PgUpCeS>m>Mfnt$>!bYIT(l zoq;tTWR?7p0#)k+E%FwET=>ER0%g8r-M@?V2AIHG&^wvfy5WmTr>g(pFf6 z&d_N7YpCMwU1*M6uykR?dQ9WFx1=bk0W$=AK7?pKhu-;1UeW~_&?CFz>|_43@aBU~ z=WFxpn0shf)3b#qp=a>G)!9eS!oWsD&RWYTj2{e)U&UJl73*6T-E}mD8ms5cpPb}? zB~vGAdbI~CE|ou`G9O^~x7^}wzbM!QX;rtqJR!6A=ZnO?Q&{IT$LTJ1LZ#iOvZHwc zSV-L(JLl*KlwY~sD8v_sg^r#Fy`-Q<-uaye z^)5r*Yip*b9w)LYrb`!iI0CcS>*SM*0Z_TMICj^^-8c}W+Id;|3zXV)*ttF$$Cmud z*6xO?&@lJBlWzGa7CLO%B-~aD)y*w2H#QAo+Ktl8o7asXtN3j~gux(=l&nZ_^bUlk zVZkd|B2S>&|52ABp92n?+OAXj-j1x{%YdovGYi!S($ZP|Tcb`ecbP5*dASh)ab+;?o;jv9d%Gvrfmp3MW>?}KZ@zA&cFMjYMhF&O)K1p8uDqz*NmM~}xg6QyGPK>t>@ zX@XDw&xiLjSR!_?jMi0*jklsETXKP#iP(GR_4|9fESz{Pqp+L>SCFsUf9A7H0aRN`kLR|1}!4G&ytKULiMEZ zavn`TEQd9D7X;FfuF0)Z^YbV+wh8rSTyjQcWEpdJRyoq1McHO_YeS2vS6^kV9o8?C z=yh&b2Bp%$seETwLVvU7+b1WAk^b9i(BzdqK8@%fR4b7H#@p{1njSZ?F#1=bj=UX~ zQZsuC{GxGK{6N-mH+^WG;&Hir>>{=t%jJ+6v&W$o?JA2DEFfKaj?~0reyml~5Yh`D z#vUcJnCX%h=zCOi`ne|udU82;_Y8SJ{?d#)i;kK=qt>eMpQs7N3UwQoDBQ;`OQXdP zet1BI6|2%HlMB1{%LLJq(;@F_LrX`T4-{?MlGS7N0Ef-;?#<1qz|1u ynCRR#yJ=$nulm^*W?BX&8rJ`sz4MR%?y}G^xA;#v>pv#={oep2*icxuHvj;Y%bIoo diff --git a/data/nn2poly_example3.rda b/data/nn2poly_example3.rda deleted file mode 100644 index b021972e817a75880177ee0d812260fd367b0a16..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27508 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 PQeFQSo>r5_3a|hGLe&io diff --git a/man/datasets.Rd b/man/datasets.Rd deleted file mode 100644 index cd72db0..0000000 --- a/man/datasets.Rd +++ /dev/null @@ -1,32 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/data.R -\docType{data} -\name{datasets} -\alias{datasets} -\alias{nn2poly_example0} -\alias{nn2poly_example1} -\alias{nn2poly_example2} -\alias{nn2poly_example3} -\title{Datasets} -\format{ -An object of class \code{list} of length 10. - -An object of class \code{list} of length 10. - -An object of class \code{list} of length 10. - -An object of class \code{list} of length 10. -} -\usage{ -nn2poly_example0 - -nn2poly_example1 - -nn2poly_example2 - -nn2poly_example3 -} -\description{ -Datasets -} -\keyword{datasets} diff --git a/tests/testthat/helper-luz.R b/tests/testthat/helper-luz.R index d517fef..22c5b70 100644 --- a/tests/testthat/helper-luz.R +++ b/tests/testthat/helper-luz.R @@ -28,8 +28,8 @@ luz_test_data <- function(example) { data_val <- torch::dataset_subset(data_full, val_indices) list( - train = torch::dataloader(data_train, batch_size = 32, shuffle = TRUE), - valid = torch::dataloader(data_val, batch_size = 32) + train = torch::dataloader(data_train, batch_size = 5, shuffle = TRUE), + valid = torch::dataloader(data_val, batch_size = 5) ) } diff --git a/tests/testthat/helper-testing_data.R b/tests/testthat/helper-testing_data.R new file mode 100644 index 0000000..99fc73e --- /dev/null +++ b/tests/testthat/helper-testing_data.R @@ -0,0 +1,36 @@ + +# Testing data 1 ---- +# Created to test with all weights equal to 1, not training any NN. +# With these values we have some tests with manually computed coefficients. +testing_helper_1 <- function(){ + testing_data_1 <- vector(mode="list", length= 0) + testing_data_1$weights_list <- vector(mode="list", length= 3) + testing_data_1$weights_list[[1]] <- matrix(1,3,2) + testing_data_1$weights_list[[2]] <- matrix(1,3,2) + testing_data_1$weights_list[[3]] <- matrix(1,3,1) + testing_data_1$af_string_list <- list("softplus", "softplus", "linear") + testing_data_1$taylor_orders <- c(2, 2, 1) + return(testing_data_1) +} + + +# Testing data 2 ---- +# In this case we will generate some polynomial data with linear output +# This data will be used in testing keras/tensorflow and luz/torch +# Note that the data is random so the NN will not learn properly but +# we can still test if the coefficients are as expected by nn2poly. + +testing_helper_2 <- function(){ + set.seed(42) + n_sample <- 100 + p <- 2 + testing_data_2 <- vector(mode="list", length= 0) + testing_data_2$train_x <- matrix(rnorm(n_sample*p),ncol = p) + testing_data_2$train_y <- matrix(rnorm(n_sample),ncol = 1) + testing_data_2$taylor_orders <- c(2, 2, 1) + return(testing_data_2) +} + + + + diff --git a/tests/testthat/test-add_constraints.R b/tests/testthat/test-add_constraints.R index 6cb4ada..fc3449f 100644 --- a/tests/testthat/test-add_constraints.R +++ b/tests/testthat/test-add_constraints.R @@ -50,6 +50,9 @@ test_that("The function works over an already trained network and the connstrain skip_if_not_installed("tensorflow") skip_on_cran() + testing_data <- testing_helper_2() + testing_data + nn <- keras_test_model() # compile the model @@ -60,10 +63,10 @@ test_that("The function works over an already trained network and the connstrain # train the model keras::fit(nn, - nn2poly_example0$train_x, - nn2poly_example0$train_y, + x = testing_data$train_x, + y = testing_data$train_y, verbose = 0, - epochs = 5, + epochs = 3, validation_split = 0.2 ) @@ -79,10 +82,10 @@ test_that("The function works over an already trained network and the connstrain # train the model keras::fit(constrained_nn, - nn2poly_example0$train_x, - nn2poly_example0$train_y, + testing_data$train_x, + testing_data$train_y, verbose = 0, - epochs = 5, + epochs = 3, validation_split = 0.2 ) diff --git a/tests/testthat/test-luz_constraint.R b/tests/testthat/test-luz_constraint.R index 6a1a2f0..bc03bfd 100644 --- a/tests/testthat/test-luz_constraint.R +++ b/tests/testthat/test-luz_constraint.R @@ -3,7 +3,9 @@ test_that("The constranied training works using the l1 and l2 constraints", { skip_if_not_installed("torch") skip_on_cran() - data <- luz_test_data(nn2poly_example0) + testing_data <- testing_helper_2() + + data <- luz_test_data(testing_data) # Do the constrained training with the l1 constraint fitted <- luz_test_model() %>% @@ -12,7 +14,7 @@ test_that("The constranied training works using the l1 and l2 constraints", { optimizer = torch::optim_adam, ) %>% add_constraints("l1_norm") %>% - fit(data$train, epochs = 3, valid_data = data$valid) + fit(data$train, epochs = 3, valid_data = data$valid, verbose = FALSE) wb <- torch::torch_tensor( rbind( @@ -36,7 +38,7 @@ test_that("The constranied training works using the l1 and l2 constraints", { optimizer = torch::optim_adam, ) %>% add_constraints("l2_norm") %>% - fit(data$train, epochs = 3, valid_data = data$valid) + fit(data$train, epochs = 3, valid_data = data$valid, verbose = FALSE) wb <- torch::torch_tensor( rbind( diff --git a/tests/testthat/test-nn2poly.R b/tests/testthat/test-nn2poly.R index 68a0e45..f991bdf 100644 --- a/tests/testthat/test-nn2poly.R +++ b/tests/testthat/test-nn2poly.R @@ -1,13 +1,11 @@ test_that("nn2poly with list input against precomputed example with single output, check also that nn2poly class is given to the output", { - nn2poly_example <- nn2poly_example0 + testing_data <- testing_helper_1() # Get the needed data - object <- nn2poly_example$weights_list - names(object) <- nn2poly_example$af_string_list - - taylor_orders <- nn2poly_example$q_taylor_vector - + object <- testing_data$weights_list + names(object) <- testing_data$af_string_list + taylor_orders <- testing_data$taylor_orders result <- nn2poly( object = object, @@ -34,11 +32,11 @@ test_that("nn2poly with list input against precomputed example with single test_that("nn2poly with list input against precomputed example with default options", { - nn2poly_example <- nn2poly_example0 + testing_data <- testing_helper_1() # Get the needed data - object <- nn2poly_example$weights_list - names(object) <- nn2poly_example$af_string_list + object <- testing_data$weights_list + names(object) <- testing_data$af_string_list result <- nn2poly( object = object @@ -96,7 +94,9 @@ test_that("nn2poly for a nn_module object", { skip_if_not_installed("torch") skip_on_cran() - data <- luz_test_data(nn2poly_example0) + testing_data <- testing_helper_2() + + data <- luz_test_data(testing_data) fitted <- luz_test_model() %>% luz::setup( @@ -109,21 +109,20 @@ test_that("nn2poly for a nn_module object", { luz::fit(data$train, epochs = 5, valid_data = data$valid, verbose = FALSE) result <- nn2poly(fitted, - taylor_orders = nn2poly_example0$q_taylor_vector, + taylor_orders = testing_data$taylor_orders, max_order = 3) - expect_equal(round(result$values[1,1],2), 0.11) - # expect_equal(result$values[2,1], -0.45410551) + expect_equal(round(result$values[1,1],2), 0.06) expect_equal(result$labels[[7]], c(1,1,1)) }) test_that("nn2poly error when wrong dimensions are given in weights", { - nn2poly_example <- nn2poly_example0 + testing_data <- testing_helper_1() # Get the needed data - object <- nn2poly_example$weights_list - names(object) <- nn2poly_example$af_string_list + object <- testing_data$weights_list + names(object) <- testing_data$af_string_list # Add weights to one layer to create the problem object[[2]] <- rbind(object[[2]], c(1,1)) diff --git a/tests/testthat/test-nn2poly_algorithm.R b/tests/testthat/test-nn2poly_algorithm.R index 72d0b87..cf3e556 100644 --- a/tests/testthat/test-nn2poly_algorithm.R +++ b/tests/testthat/test-nn2poly_algorithm.R @@ -2,12 +2,12 @@ test_that("nn2poly_algorithm against precomputed example", { # Load the example: - nn2poly_example <- nn2poly_example0 + testing_data <- testing_helper_1() # Get the needed data - weights_list <- nn2poly_example$weights_list - af_string_list <- nn2poly_example$af_string_list - taylor_orders <- nn2poly_example$q_taylor_vector + weights_list <- testing_data$weights_list + af_string_list <- testing_data$af_string_list + taylor_orders <- testing_data$taylor_orders result <- nn2poly_algorithm( weights_list = weights_list, diff --git a/tests/testthat/test-parameters.R b/tests/testthat/test-parameters.R index 1cee199..24a7c9f 100644 --- a/tests/testthat/test-parameters.R +++ b/tests/testthat/test-parameters.R @@ -45,5 +45,5 @@ test_that("The get_parameters function works for a torch model (nn_module) nn <- luz_test_model() params <- get_parameters(nn) - expect_equal(params$af_string_list, nn2poly_example0$af_string_list) + expect_equal(params$af_string_list, list("softplus", "softplus", "linear")) }) diff --git a/tests/testthat/test-plot_n_important_coeffs.R b/tests/testthat/test-plot_n_important_coeffs.R index a97875a..3f06dd6 100644 --- a/tests/testthat/test-plot_n_important_coeffs.R +++ b/tests/testthat/test-plot_n_important_coeffs.R @@ -1,9 +1,9 @@ test_that("Test the plot for a polynomial generated `keep_layers = FALSE`", { # loading the example - nn2poly_example <- nn2poly_example0 - object <- nn2poly_example$weights_list - names(object) <- nn2poly_example$af_string_list - taylor_orders <- nn2poly_example$q_taylor_vector + testing_data <- testing_helper_1() + object <- testing_data$weights_list + names(object) <- testing_data$af_string_list + taylor_orders <- testing_data$taylor_orders # computing the polynomial result <- nn2poly( @@ -21,10 +21,10 @@ test_that("Test the plot for a polynomial generated `keep_layers = FALSE`", { test_that("Test the plot for a polynomial generated `keep_layers = TRUE`", { # loading the example - nn2poly_example <- nn2poly_example0 - object <- nn2poly_example$weights_list - names(object) <- nn2poly_example$af_string_list - taylor_orders <- nn2poly_example$q_taylor_vector + testing_data <- testing_helper_1() + object <- testing_data$weights_list + names(object) <- testing_data$af_string_list + taylor_orders <- testing_data$taylor_orders # computing the polynomial result <- nn2poly( diff --git a/tests/testthat/test-plot_taylor_and_activation_potentials.R b/tests/testthat/test-plot_taylor_and_activation_potentials.R index c367511..1336b8a 100644 --- a/tests/testthat/test-plot_taylor_and_activation_potentials.R +++ b/tests/testthat/test-plot_taylor_and_activation_potentials.R @@ -6,6 +6,8 @@ test_that("The function works as expected", { skip_on_covr() skip_on_ci() + testing_data <- testing_helper_2() + nn <- keras_test_model() # compile the model @@ -16,8 +18,8 @@ test_that("The function works as expected", { # train the model keras::fit(nn, - nn2poly_example0$train_x, - nn2poly_example0$train_y, + testing_data$train_x, + testing_data$train_y, verbose = 0, epochs = 30, validation_split = 0.3 @@ -26,8 +28,8 @@ test_that("The function works as expected", { # compute the different plots plots <- plot_taylor_and_activation_potentials( object = nn, - data = cbind(nn2poly_example0$train_x, nn2poly_example0$train_y), - taylor_orders = nn2poly_example0$q_taylor_vector, + data = cbind(testing_data$train_x, testing_data$train_y), + taylor_orders = testing_data$taylor_orders, max_order = 3, constraints = FALSE) diff --git a/vignettes/source/nn2poly-00-data.Rmd.orig b/vignettes/source/nn2poly-00-data.Rmd.orig deleted file mode 100644 index 8d79a75..0000000 --- a/vignettes/source/nn2poly-00-data.Rmd.orig +++ /dev/null @@ -1,563 +0,0 @@ ---- -title: "03 - Generating data to test the implementation" -output: rmarkdown::html_vignette -vignette: > - %\VignetteIndexEntry{03 - Generating data to test the implementation} - %\VignetteEngine{knitr::rmarkdown} - %\VignetteEncoding{UTF-8} ---- - -```{r, include = FALSE} -knitr::opts_chunk$set( - eval = FALSE, - collapse = TRUE, - comment = "#>", - fig.path = "figure/nn2poly-03-" -) -``` - -This vignette will generate data necessary for the package examples and unit tests but does not explicitly showcase the usage of the package functions. - -There will be 4 examples generated and stored as `nn2poly_exampleX` where `X` denotes the number of the example, from 0 to 4. - - -```{r setup} -library(nn2poly) -library(nn2poly.tools) -library(keras) -library(tensorflow) -tensorflow::tf$random$set_seed(42) -set.seed(42) -``` - -## Example 0: - -This example is a simplified and different from the following ones. The weights will be manually set to be matrices of 1's, so we can manually compute some of the coefficients obtained internally by the algorithm and use them to check it works as expected. - -- The parameters for `nn2poly_example0`: - - Number of variables $p$: 2. - - Number of hidden layers: 2. - - Single linear output (regression). - - Taylor order at each hidden layer: 2. - - Softplus activation function. - - -```{r} - -# Main parameters -p <- 2 -my_fun <-"softplus" -my_q_taylor <- 2 - -af_string_list <- list(my_fun, my_fun, "linear") -taylor_orders <- c(my_q_taylor, my_q_taylor, 1) # If the output is linear, the last value should be 1 so it doesn't affect the product - -af_derivatives_list <- nn2poly::obtain_derivatives_list(af_string_list,taylor_orders) - -# Directly assgin the wegiths as 1's to compute everything. - -weights_list <- vector(mode="list", length= 3) -weights_list[[1]] <- matrix(1,3,2) -weights_list[[2]] <- matrix(1,3,2) -weights_list[[3]] <- matrix(1,3,1) - - -# Store all the data needed for the examples -------------------------- -nn2poly_example0 <- vector(mode="list", length= 0) - - -nn2poly_example0$weights_list <- weights_list -nn2poly_example0$af_string_list <- af_string_list -nn2poly_example0$af_derivatives_list <- af_derivatives_list -nn2poly_example0$taylor_orders <- taylor_orders - -#save(nn2poly_example0, file ="data/nn2poly_example0.rda") - - -``` - -## Example 1: - -2 variables, original order 2, 2 hidden layers, taylor order 2, LINEAR (so using Taylor should be exact), 2 hidden neurons per layer. - -```{r example-1} - -# Main parameters -p <- 2 -q_original <- 2 -my_fun <-"linear" -my_q_taylor <- 2 -my_h <- 2 - -af_string_list <- list(my_fun, my_fun, "linear") -taylor_orders <- c(my_q_taylor, my_q_taylor, 1) # If the output is linear, the last value should be 1 so it doesn't affect the product -h_neurons_vector <- c(my_h, my_h, 1) # If the output is linear, the last value should be 1 -my_max_norm <- list("l1_norm", 1) -af_derivatives_list <- nn2poly::obtain_derivatives_list(af_string_list,taylor_orders) - -# Fixed parameters for the data generation -n_sample <- 400 -mean_range <- c(-100, 100) -beta_range <- c(-5, 5) -error_var <- 0.2 - -# Data generation: -data_generated <- generate_normal_data(n_sample, p, q_original, mean_range, beta_range, error_var) -data <- data_generated$data -original_betas <- data_generated$original_betas - -# Scale the data in the desired interval and separate train and test -scale_method <- "-1,1" -data_scaled <- scale_data(data, scale_method) -aux <- divide_train_test(data_scaled, train_proportion = 0.75) -train <- aux$train -test <- aux$test - -# NN (keras) hyperparameters -my_loss <- "mse" -my_metrics <- "mse" -my_optimizer <- optimizer_adamax() -my_epochs <- 300 -my_validation_split <- 0.3 -my_verbose <- 0 - -# NN training --------------------------------- - -# Divide again in x and y to train the NN with keras -train_x <- as.matrix(subset(train, select = -c(p+1))) -train_y <- as.matrix(subset(train, select = c(p+1))) - -test_x <- as.matrix(subset(test, select = -c(p+1))) -test_y <- as.matrix(subset(test, select = c(p+1))) - -# Build the nn -nn <- build_keras_model( - p, - af_string_list, - h_neurons_vector, - my_max_norm -) - -# Compile the model -compile(nn, - loss = my_loss, - optimizer = my_optimizer, - metrics = my_metrics -) - -# Fit the model -history <- fit(nn, - train_x, - train_y, - verbose = my_verbose, - epochs = my_epochs, - validation_split = my_validation_split, - batch_size = 500 -) - -# Visualize the training process -plot(history) - - -# Extract the weights: - keras_weights <- keras::get_weights(nn) - - # En este caso solo hace falta cambiar lo de la ultima capa - # ARREGLAR ESTO PARA QUE SEA CONSISTENTE - - n <- length(keras_weights) - - if(my_max_norm[[1]]=="no_constraint"){ - - n2 <- n/2 - - nn_weights <- vector(mode = "list", length = n2) - for (i in 1:n2){ - nn_weights[[i]] <- rbind(keras_weights[[2*i]], keras_weights[[2*i-1]]) - } - - } else { - nn_weights <- keras_weights[1:(n - 2)] - - nn_weights[[n - 1]] <- rbind(keras_weights[[n]], keras_weights[[n - 1]]) - } - -weights_list <- nn_weights - - - - - -# Store all the data needed for the examples -------------------------- -nn2poly_example1 <- vector(mode="list", length= 0) - - -nn2poly_example1$weights_list <- weights_list -nn2poly_example1$coefficients <- original_betas -nn2poly_example1$af_string_list <- af_string_list -nn2poly_example1$af_derivatives_list <- af_derivatives_list -nn2poly_example1$taylor_orders <- taylor_orders -nn2poly_example1$h_neurons_vector <- h_neurons_vector -nn2poly_example1$train_x <- train_x -nn2poly_example1$train_y <- train_y -nn2poly_example1$test_y <- test_y -nn2poly_example1$test_x <- test_x - -#save(nn2poly_example1, file ="data/nn2poly_example1.rda") - - -``` - - -## Example 2: - -2 variables, original order 2, 2 hidden layers, taylor order 2, softplus, 2 hidden neurons per layer - -```{r example-2} - -# Main parameters -p <- 2 -q_original <- 2 -my_fun <-"softplus" -my_q_taylor <- 2 -my_h <- 2 - -af_string_list <- list(my_fun, my_fun, "linear") -taylor_orders <- c(my_q_taylor, my_q_taylor, 1) # If the output is linear, the last value should be 1 so it doesn't affect the product -h_neurons_vector <- c(my_h, my_h, 1) # If the output is linear, the last value should be 1 -my_max_norm <- list("l1_norm", 1) -af_derivatives_list <- nn2poly::obtain_derivatives_list(af_string_list,taylor_orders) - -# Fixed parameters for the data generation -n_sample <- 400 -mean_range <- c(-100, 100) -beta_range <- c(-5, 5) -error_var <- 0.2 - -# Data generation: -data_generated <- generate_normal_data(n_sample, p, q_original, mean_range, beta_range, error_var) -data <- data_generated$data -original_betas <- data_generated$original_betas - -# Scale the data in the desired interval and separate train and test -scale_method <- "-1,1" -data_scaled <- scale_data(data, scale_method) -aux <- divide_train_test(data_scaled, train_proportion = 0.75) -train <- aux$train -test <- aux$test - -# NN (keras) hyperparameters -my_loss <- "mse" -my_metrics <- "mse" -my_optimizer <- optimizer_adamax() -my_epochs <- 300 -my_validation_split <- 0.3 -my_verbose <- 0 - -# NN training --------------------------------- - -# Divide again in x and y to train the NN with keras -train_x <- as.matrix(subset(train, select = -c(p+1))) -train_y <- as.matrix(subset(train, select = c(p+1))) - -test_x <- as.matrix(subset(test, select = -c(p+1))) -test_y <- as.matrix(subset(test, select = c(p+1))) - -# Build the nn -nn <- build_keras_model( - p, - af_string_list, - h_neurons_vector, - my_max_norm -) - -# Compile the model -compile(nn, - loss = my_loss, - optimizer = my_optimizer, - metrics = my_metrics -) - -# Fit the model -history <- fit(nn, - train_x, - train_y, - verbose = my_verbose, - epochs = my_epochs, - validation_split = my_validation_split, - batch_size = 500 -) - -# Visualize the training process -plot(history) - - -# Extract the weights: - keras_weights <- keras::get_weights(nn) - - # En este caso solo hace falta cambiar lo de la ultima capa - # ARREGLAR ESTO PARA QUE SEA CONSISTENTE - - n <- length(keras_weights) - - if(my_max_norm[[1]]=="no_constraint"){ - - n2 <- n/2 - - nn_weights <- vector(mode = "list", length = n2) - for (i in 1:n2){ - nn_weights[[i]] <- rbind(keras_weights[[2*i]], keras_weights[[2*i-1]]) - } - - } else { - nn_weights <- keras_weights[1:(n - 2)] - - nn_weights[[n - 1]] <- rbind(keras_weights[[n]], keras_weights[[n - 1]]) - } - -weights_list <- nn_weights - - - - - -# Store all the data needed for the examples -------------------------- -nn2poly_example2 <- vector(mode="list", length= 0) - - -nn2poly_example2$weights_list <- weights_list -nn2poly_example2$coefficients <- original_betas -nn2poly_example2$af_string_list <- af_string_list -nn2poly_example2$af_derivatives_list <- af_derivatives_list -nn2poly_example2$taylor_orders <- taylor_orders -nn2poly_example2$h_neurons_vector <- h_neurons_vector -nn2poly_example2$train_x <- train_x -nn2poly_example2$train_y <- train_y -nn2poly_example2$test_y <- test_y -nn2poly_example2$test_x <- test_x - -#save(nn2poly_example2, file ="data/nn2poly_example2.rda") - - -``` - - - -## Example 3: - -3 variables, original order 3, 3 hidden layers, taylor order 3, tanh, 50 neurons per layer - -```{r example-3} - -# Main parameters -p <- 3 -q_original <- 3 -my_fun <-"tanh" -my_q_taylor <- 3 -my_h <- 50 - -af_string_list <- list(my_fun, my_fun, my_fun, "linear") -taylor_orders <- c(my_q_taylor, my_q_taylor, my_q_taylor, 1) # If the output is linear, the last value should be 1 so it doesn't affect the product -h_neurons_vector <- c(my_h, my_h, 1) # If the output is linear, the last value should be 1 -my_max_norm <- list("l1_norm", 1) -af_derivatives_list <- nn2poly::obtain_derivatives_list(af_string_list,taylor_orders) - -# Fixed parameters for the data generation -n_sample <- 400 -mean_range <- c(-100, 100) -beta_range <- c(-5, 5) -error_var <- 0.2 - -# Data generation: -data_generated <- generate_normal_data(n_sample, p, q_original, mean_range, beta_range, error_var) -data <- data_generated$data -original_betas <- data_generated$original_betas - -# Scale the data in the desired interval and separate train and test -scale_method <- "-1,1" -data_scaled <- scale_data(data, scale_method) -aux <- divide_train_test(data_scaled, train_proportion = 0.75) -train <- aux$train -test <- aux$test - -# NN (keras) hyperparameters -my_loss <- "mse" -my_metrics <- "mse" -my_optimizer <- optimizer_adamax() -my_epochs <- 300 -my_validation_split <- 0.3 -my_verbose <- 0 - -# NN training --------------------------------- - -# Divide again in x and y to train the NN with keras -train_x <- as.matrix(subset(train, select = -c(p+1))) -train_y <- as.matrix(subset(train, select = c(p+1))) - -test_x <- as.matrix(subset(test, select = -c(p+1))) -test_y <- as.matrix(subset(test, select = c(p+1))) - -# Build the nn -nn <- build_keras_model( - p, - af_string_list, - h_neurons_vector, - my_max_norm -) - -# Compile the model -compile(nn, - loss = my_loss, - optimizer = my_optimizer, - metrics = my_metrics -) - -# Fit the model -history <- fit(nn, - train_x, - train_y, - verbose = my_verbose, - epochs = my_epochs, - validation_split = my_validation_split, - batch_size = 500 -) - -# Visualize the training process -plot(history) - - -# Extract the weights: - keras_weights <- keras::get_weights(nn) - - # En este caso solo hace falta cambiar lo de la ultima capa - # ARREGLAR ESTO PARA QUE SEA CONSISTENTE - - n <- length(keras_weights) - - if(my_max_norm[[1]]=="no_constraint"){ - - n2 <- n/2 - - nn_weights <- vector(mode = "list", length = n2) - for (i in 1:n2){ - nn_weights[[i]] <- rbind(keras_weights[[2*i]], keras_weights[[2*i-1]]) - } - - } else { - nn_weights <- keras_weights[1:(n - 2)] - - nn_weights[[n - 1]] <- rbind(keras_weights[[n]], keras_weights[[n - 1]]) - } - -weights_list <- nn_weights - - - - - -# Store all the data needed for the examples -------------------------- -nn2poly_example3 <- vector(mode="list", length= 0) - -nn2poly_example3$weights_list <- weights_list -nn2poly_example3$coefficients <- original_betas -nn2poly_example3$af_string_list <- af_string_list -nn2poly_example3$af_derivatives_list <- af_derivatives_list -nn2poly_example3$taylor_orders <- taylor_orders -nn2poly_example3$h_neurons_vector <- h_neurons_vector -nn2poly_example3$train_x <- train_x -nn2poly_example3$train_y <- train_y -nn2poly_example3$test_y <- test_y -nn2poly_example3$test_x <- test_x - -#save(nn2poly_example3, file ="data/nn2poly_example3.rda") - - -``` - - - -## Some small Keras NNs - -These keras NNs are designed to be used when testing. - - - -Small unconstrained NN: -```{r} -set.seed(42) -tensorflow::tf$random$set_seed(42) - -nn <- keras_model_sequential() - -nn %>% layer_dense(units = 2, - activation = "tanh", - input_shape = 2) - -nn %>% layer_dense(units = 3, - activation = "softplus") - -nn %>% layer_dense(units = 2, - activation = "linear") - -nn -``` - -```{r} -nn2poly:::get_model_parameters(nn) -``` - -NN with constraints (this depends on `add_constraints` working properly.) - -```{r} -nn2 <- add_constraints(nn) - -nn2 -``` - - - -```{r} -nn2poly:::get_model_parameters(nn2) -``` - - -Usando la forma que teniamos en build_keras model. Tienen que ser entrenadas. - -```{r} -params <- get_model_parameters(nn) - -nn <- build_keras_model(params$p, - params$af_string_list, - params$n_neurons, - my_max_norm) - -nn <- nn$build(input_shape = ) - -nn - -``` -```{r} -compile(nn, - loss = my_loss, - optimizer = my_optimizer, - metrics = my_metrics -) - -# Fit the model -history <- fit(nn, - train_x, - train_y, - verbose = my_verbose, - epochs = 2, - validation_split = my_validation_split, - batch_size = 50 -) -``` - - -```{r} -get_model_parameters(nn) -nn$layers[[1]]$get_weights()[[1]] - -``` - diff --git a/vignettes/source/nn2poly-00-tests.Rmd.orig b/vignettes/source/nn2poly-00-tests.Rmd.orig deleted file mode 100644 index e975bc2..0000000 --- a/vignettes/source/nn2poly-00-tests.Rmd.orig +++ /dev/null @@ -1,105 +0,0 @@ ---- -title: "nn2poly-04-testing_the_implementation_with_generated_data" -output: rmarkdown::html_vignette -vignette: > - %\VignetteIndexEntry{nn2poly-04-testing_the_implementation_with_generated_data} - %\VignetteEngine{knitr::rmarkdown} - %\VignetteEncoding{UTF-8} ---- - -```{r, include = FALSE} -knitr::opts_chunk$set( - collapse = TRUE, - comment = "#>", - fig.path = "figure/nn2poly-04-" -) -``` - -```{r setup} -library(nn2poly) -library(keras) -library(tensorflow) -``` - -This vignette contains several usecases of the `nn2poly` package applied to some precomputed examples that allow us to test special situations and control the behavior of the NN2Poly algorithm. - -## Example 0 - -```{r} - - nn2poly_example <- nn2poly_example0 - - # Get the needed data - weights_list <- nn2poly_example$weights_list - af_string_list <- nn2poly_example$af_string_list - af_derivatives_list <- nn2poly_example$af_derivatives_list - taylor_orders <- nn2poly_example$taylor_orders - - result <- nn2poly_algorithm( - weights_list = weights_list, - af_string_list = af_string_list, - taylor_orders = taylor_orders, - keep_layers = TRUE - ) - - # Comparamos el potencial en la segunda capa para neurona 1 - # Note that in new, 2 denotes neuron 1 as 1 are the labels - print("Potential u at layer 2, neuron 1") - print(result[[3]][[2]]) - - print("Output y at layer 2, neuron 1") - print(result[[4]][[1]][4]) - print(result[[4]][[2]][4]) - - print(1/2*result[[3]][[2]][4]+1/8*result[[3]][[2]][2]^2+ - 1/4*result[[3]][[2]][1]*result[[3]][[2]][4]) - - 0.633518334 - - - -``` - - - -## Example 1 - -```{r example-1} - - nn2poly_example <- nn2poly_example1 - - # Get the needed data - weights_list <- nn2poly_example$weights_list - af_string_list <- nn2poly_example$af_string_list - af_derivatives_list <- nn2poly_example$af_derivatives_list - taylor_orders <- nn2poly_example$taylor_orders - test_y <- nn2poly_example$test_y - test_x <- nn2poly_example$test_x - - result <- nn2poly_algorithm( - weights_list = weights_list, - af_string_list = af_string_list, - taylor_orders = taylor_orders, - keep_layers = TRUE - ) - - labels <- result[[length(historical_coeffs)]][[1]] - coeffs <- result[[length(historical_coeffs)]][[2]] - - # Obtain the predicted values for the test data with our Polynomial Regression - n_test <- length(test_y) - prediction_PR <- rep(0, n_test) - - for (i in 1:n_test) { - prediction_PR[i] <- eval_poly(test_x, labels = labels, coeffs = coeffs) - } - - # FALTA AÑADIR LA NN A LOS DATA PARA PODER USAR PREDICT - - # Obtain the predicted values with the NN to compare them - prediction_NN <- predict(nn, test_x) - - plot_NN_PR_comparison(prediction_PR, prediction_NN) -``` - -