From a9235e9c17326b0c5b74f7c794e862737d65d2fe Mon Sep 17 00:00:00 2001 From: Brett Laptop Date: Tue, 6 Aug 2024 21:34:30 -0400 Subject: [PATCH] evil --- CMakeLists.txt | 2 +- include/config.h | 12 +++- include/custom_transformer.h | 76 ++++++++++++++++++++ include/helper.h | 1 + include/image_operations.h | 2 + include/images.h | 3 + lib/blt-gp | 2 +- meow.jpg | Bin 0 -> 36690 bytes src/custom_transformer.cpp | 130 ++++++++++++++++++++++++++++++++++- src/main.cpp | 4 -- 10 files changed, 223 insertions(+), 9 deletions(-) create mode 100644 meow.jpg diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d3fe00..1232fc6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.25) -project(image-gp-6 VERSION 0.0.20) +project(image-gp-6 VERSION 0.0.21) include(FetchContent) diff --git a/include/config.h b/include/config.h index 3f60150..ae49026 100644 --- a/include/config.h +++ b/include/config.h @@ -19,13 +19,15 @@ #ifndef IMAGE_GP_6_CONFIG_H #define IMAGE_GP_6_CONFIG_H +#include + inline constexpr size_t log2(size_t n) // NOLINT { return ((n < 2) ? 1 : 1 + log2(n / 2)); } -//inline const blt::u64 SEED = std::random_device()(); -inline const blt::u64 SEED = 553372510; +inline const blt::u64 SEED = std::random_device()(); +//inline const blt::u64 SEED = 553372510; inline constexpr blt::size_t IMAGE_SIZE = 128; inline constexpr blt::size_t IMAGE_PADDING = 16; inline constexpr blt::size_t POP_SIZE = 64; @@ -35,9 +37,15 @@ inline constexpr blt::size_t DATA_CHANNELS_SIZE = DATA_SIZE * CHANNELS; inline constexpr blt::size_t BOX_COUNT = static_cast(log2(IMAGE_SIZE / 2)); inline constexpr float THRESHOLD = 0.3; inline constexpr auto load_image = "../GSab4SWWcAA1TNR.png"; + +inline blt::gp::image_crossover_t image_crossover; +inline blt::gp::image_mutation_t image_mutation; + //inline constexpr auto load_image = "../miles.png"; inline blt::gp::prog_config_t config = blt::gp::prog_config_t() + .set_crossover(image_crossover) + .set_mutation(image_mutation) .set_initial_min_tree_size(4) .set_initial_max_tree_size(8) .set_elite_count(2) diff --git a/include/custom_transformer.h b/include/custom_transformer.h index 0a3b550..c5a5830 100644 --- a/include/custom_transformer.h +++ b/include/custom_transformer.h @@ -19,4 +19,80 @@ #ifndef IMAGE_GP_6_CUSTOM_TRANSFORMER_H #define IMAGE_GP_6_CUSTOM_TRANSFORMER_H +#include + +namespace blt::gp +{ + template + inline static constexpr double sum(const T& array) + { + double init = 0.0; + for (double i : array) + init += i; + return init; + } + + template + static constexpr std::array aggregate_array(Args... list) + { + std::array data {list...}; + auto total_prob = sum(data); + double sum_of_prob = 0; + for (auto& d : data) { + auto prob = d / total_prob; + d = prob + sum_of_prob; + sum_of_prob += prob; + } + return data; + } + + class image_crossover_t : public crossover_t + { + public: + image_crossover_t() = default; + + explicit image_crossover_t(const config_t& config): crossover_t(config) + {} + + blt::expected apply(gp_program& program, const tree_t& p1, const tree_t& p2) final; + }; + + class image_mutation_t : public mutation_t + { + public: + enum class mutation_operator : blt::i32 + { + EXPRESSION, // Generate a new random expression + ADJUST, // adjust the value of the type. + FUNC, // Change node into a different function. Args will be generated / removed. + SUB_FUNC, // subexpression becomes argument to new random function. Other args are generated. + JUMP_FUNC, // subexpression becomes this new node. Other arguments discarded. + COPY, // node can become copy of another subexpression. + END, // helper + }; + + image_mutation_t() = default; + + explicit image_mutation_t(const config_t& config): mutation_t(config) + {} + + tree_t apply(gp_program& program, const tree_t& p) final; + + private: + static constexpr auto operators_size = static_cast(mutation_operator::END); + private: + // this value is adjusted inversely to the size of the tree. + double per_node_mutation_chance = 1.0; + + static constexpr std::array mutation_operator_chances = aggregate_array( + 0.01, // EXPRESSION + 0.11, // ADJUST + 0.05, // FUNC + 0.01, // SUB_FUNC + 0.1, // JUMP_FUNC + 0.05 // COPY + ); + }; +} + #endif //IMAGE_GP_6_CUSTOM_TRANSFORMER_H diff --git a/include/helper.h b/include/helper.h index d023391..3481504 100644 --- a/include/helper.h +++ b/include/helper.h @@ -20,6 +20,7 @@ #define IMAGE_GP_6_HELPER_H #include +#include template constexpr static auto make_single(SINGLE_FUNC&& func) diff --git a/include/image_operations.h b/include/image_operations.h index 330939b..0998569 100644 --- a/include/image_operations.h +++ b/include/image_operations.h @@ -16,9 +16,11 @@ * along with this program. If not, see . */ +#include #include #include #include +#include #ifndef IMAGE_GP_6_IMAGE_OPERATIONS_H #define IMAGE_GP_6_IMAGE_OPERATIONS_H diff --git a/include/images.h b/include/images.h index 5e39812..73772aa 100644 --- a/include/images.h +++ b/include/images.h @@ -20,6 +20,9 @@ #define IMAGE_GP_6_IMAGES_H #include +#include +#include +#include struct full_image_t { diff --git a/lib/blt-gp b/lib/blt-gp index 593e02b..b10b438 160000 --- a/lib/blt-gp +++ b/lib/blt-gp @@ -1 +1 @@ -Subproject commit 593e02b6ffd36cfabda85e9dcfd88ec60b8a8741 +Subproject commit b10b4388897b1673b0dbe84b1db34584db0e9660 diff --git a/meow.jpg b/meow.jpg new file mode 100644 index 0000000000000000000000000000000000000000..366ed0a9ec1d45a556be0012aa146d781b2e1ce3 GIT binary patch literal 36690 zcmdSAcUV)+_9(mwMXJ)9s1QQvJro;)5FkM4gc=Eed@20Sgt)1|h6@Z5N z`!hK?2m1X5{mUzr>fr5Pv{SPGlH&i2WO8v0bf%K*QU8zt>dUEZ;-EaCp2VC;W_o&5q%=@Y3m*L=K#Pv3Q#PPt=s^|i8~ z=BM%z0s;YZKo7Wi%0KmCvkb>-@9wO;<4RK)#CBr{ilUicd{;9EO}v)Q%o`{yZz+K&8J?NJSY(gl(NZ zTlnh0>Bse!hmq&z^A%`w{sBJTJDB;-dc!TK`>gvvz)Pz_R>4-@$26Al?>zRNhe z1q<-91zvpBa(4oIqWExi;Wq$Jpu9=of)d~V`p4a?!?Uxeq(Pcq#$IzFEsIo&Aw%ay z^L4!h%5R`!Iy7Tc^+>EV@J4{o%aYUHFmYLY=JEMK!QmC8%2Gnvl9$c|f|+ziE}N`wjG9Pj2kqSi0)?fkb^$t;bJ)+9=>XX(!H_ zayRSiqoq1ZZs2bqvhQWdulIW50ZbFQ)uCwQU1+PoM$$!9q;q<7PmI}_PzP$1$8n1(A-1>*s zJzB~-RUM&I@_3yz^NyFV7EM0*KR8vJ8&s{lg5h}m>%zh#?F7oDS6!zi$=Njjf52S) zv(5ddL*+5w{BIzz5=vFHKRg}x)Tx3@`-5R-oyrqcEoMT~JUlxdwW~gz!2Sj*U;6zy zRNaw98htZ?xB6RtQ6EqEr)=NEvI+eL{_6bfmwr2ssH56lx8K=n?B}aLDSrb2oO1{L zr@BY2d#aHulnW=Cet>R0npkt3_zn2|9BF$+|f0jIm zlxcQ-)##HnHL-r8G~2NAh}siwwb%HF8M#958+L+!8UD%AwN_-y6}xMveK$gJ9XjS7 zyiUn|lmxxe^lR-8x#jnIDW{Eieuc#(@_g{K?A}&%>&szhs`_%yAGAwn{?&}YReSZt z7thxd5*<}`JuOLZ-uZt}7#%#DCHUR8KhMAQqhx5BoA*8$y68JBriy9u1vb=JS zPIl2hZk+bw+?QO9-OmU;Nc)2n$MP|uabsDfPnQ!PofR3Ftx>G^5AJkz2A=^v` z{01I}6i^N9jop7}E_IxTosmDfgQJ?*reCW+t~Q_c?Wt-2|B3jFDG)2HO%uxi(&ps< z55xYiAbO^vxoi#>JLm*&G&|OX7{WbN8O_#T#NnjU!>8|^KrtXO!7LYDHgW`AJVXZD ztK+l+Y+%|Ay%%CUMKz2!z1!piimjMz)#Jc80X8-cnfMo5#pc?@mQ41n#W6AKngkj! zT9^P$(@cYegW)%e!m?TEXjo4@s(+I>c;n(~nCprRTev)sG!|Sg3kdcHVuNQruR=r(Tx%RdE-u6`oqFc;R1A_pFKa9VYv5l+~ z&J++sb%200jZ)DLwr7BjkDYjje;h!!y3~M6af-hl+ubXr8u+77lzPWKxZ+oa&2bRjG_|=n zQ%GeS2VJ|^8Kc^_VVt3?(>J-!vva#m>v17EMNfRMv_S&zs7bn)ZVUaWHek*bTq1r= zomtB|86HWWLJ>FiZ*W04{Rz$9Q@iGa21YpNN!G!Nx6UJUJGNyA6%Q|Uyuf)uC)R&9 z{9oky7y#r9a8b-sJNDwCJMknP0#?7JULpmNxh4yV)!3|K_ZYP`i8N*?b8cG8Q9kCfO|V9@^X@UV_I3Uw(EzX^|lM%eP08`Hp0c1;z|nv z5EpxQ5ztKouu0PZ3#GyU=(TAe{?@uR=c}Z)ha5ujx$cImGB&b@CAn%oY5r$Fj@ppK zqenK(7%#(WIwtR?!)9&)TL=pmTgj(=L*pR9T`4*N-2QL^BNW zg=||>d<5xYN5>TxVzaO}@y(21z8~LMFc3d)>HAJW_4_2nsc*XE76R=o8i1_k_BVLQ z_LTdNaR|Pw=X_Hcd!~cbj|aw?k$yg3M`t5N(GKi)zu!au(za>3mC0qXsRDn@r(NS; zIl32IBv(pw%cJxcLXP+~{}o^V#DQ*yiKzbIZt-sQ4y)lP^vGb&$xOwudyuNZ6GS-n zL0mKZK-%x~9hlreD0-BIR5^N%lqIgDA`oyTyVRl*hrPXVw~qWbTxiaxLxHa=88^j&fyb0CmTfJbEG!1J@SfYQm0J??;@K%Sp`|l z@MCU`5R&-dMqFWgqJ=MBZM&g)nz&+zRK}_GUh$7|qBGF%d76uW`voq`Ow|^k^h_cW z{R4@HL#XEr1@)*|#`)UHRgWiGe6I%D%dOhUGL~T*h(&Lai&YT#3tKnt?*xNh%-9(w zTeP4GTibAnx*=x@VdlP5`ItnC;dbIg)OKfMMyY_vaSto*pt^f~+;~ebqX%!KDV+(wf1t;P5ht zTg+cOl(Q4?4Oj3S(vN&-9a+}u**O(eAh8t^N|+p5^~`EgkygDfB`7_xBfcA#@un{f zr4aVdHvjjWZmz(Iq}I)z6#!EO)rzpi4wrys{S0($NKP|M(PCxf-0LK& z#$<>>9bbDXx!@435*xQKcPcdB6H2M}Imv(i`TB|@HQ&Sr07X7P`5UVe0*!9B?p zQ|bA5-V}ADcjnIY`UteR<9mE1F0j8JK9gXUX@(Txohv=VcfY+q7R)csC1{spVz zm8?J`6~6&IDorQ&XfhHfnt5^oee14k|6pMHNwWYix?;wVju7dYqs2QsGP`s2+jM~8 z_tyJ)m)D8RR4-yb8`-nqbFswf-9|ZSgYb|~%kt|i1cV9ycWM9Idr(+H zC|epx#)JeFpBpYt<6Fw%TauEA6Q7Hd>T`kL5fc#`N|H;#-eMdii5gXrmk?(k^n@r| zK@cI}xcVLmYWPc)(N(7q$Jjju`zCUbyfrP-JL>7#XQ6*V@hqhgiFJZXqxWd|-7XuGKXt1p5aPtJW7 zy-D#D4u!r6>5_^%e{h8hZ|3vFIrOa2K(&WP@*UUk9|_)(O5mZSPEKhk zBftOxXx*ZJ1F?xoL|A>Je5L2rYG(iUbMqCCjX0H^wwO+c{=;33!{cvNoA*mbTsmBR zQ>^kO*YGdTFx%lIuiSzcCqc!pkzpaIOg8!6#79hR+r6b3X@y;W=NN?e#@8HdQBret+UB>WfKllkw_=oU zo0ZGeq&=`Q;z0PM(cC*agV6X>&OJp5A2g-hs(wdWGyrlq(Ha}G&MG&dT^u@D7^;iR7zEL;^a?M};YNV_5UlzbHb31s#?nAF2Va}- z_)VeqK(3DZ6qJByWKt*YB&R+PB}~WK?*S_ag4UUSU}4TAi1uX2k(-_;Naa}=ec7=) z&e{$(?}wDly(Kw6%N|zPOx7>Y&#Z6_RE%{6fY=y-M)NzK`9Rp7UWWX{x z4BR<_kfAiJOd?rH$w9zV+L-7Tb)<||+=y38K^Ec;_%v!S@TC}+MT-FLj%C$Cq~pr&-nbM!m9TEz=lqBef~~0B8fhI?rv(zaVPXb$fJ5 zs;T1)PWkofqqDgDpK^|I^kXpH_emZ!At1>x8yi;5@UQ}gP`sBsLyVP#xHRapy8t7;+0E|)JqY@A8V%M3)#!!uL7{Dw7BW`@@+_Y=E z^}ZxaykH6Ywl}z~GPdG<@{nU{4tS$&&!$SKUlVdn^dWORuC2Fm zZo5ncr*uEmJiSh|D!Otq-Q1{lJu=JWS}57ia!Rjktkf2>V32&Vgk?~*CgPK-vS>xq zs;!DC(oy2Q*zL&4?_PT18HoC;^JbLh)DMF^Ye{q%e7sI1^i;C{*LJ=DE8ihL7YPWH zm1Git>^?zV9fZb)Ef8KU$aI(8;CdWK3RbtW+A$Bmt4qBoK>%r*Fx&I3bOb?g91ka& zd{;QGxa`!x^9p0wH3rWGBHUMYPjlRsPTglWjINUT&PrPR2Y@D;5n0;Psl{qO3M=kv zGLvQRmzgqxWZi?Cx73kpxZ%jY&Va(+`O zlZ%nhKf)nW@bkLG;9%f&b>xqv1@&*bFLWPR3PF!(%L=E(>2j|aX1KFx=Hf)#lBe&9 znt4)y@U&`x?i~Ol3a{jzC!*&a8vE}#2CT^%r0JF@4KnQ5qI|ra&KPZ(T%C3)e}|^I zU|eo-`^lNIsZiA7&eBV0JSkXC-(&yTz590S3*GZV(jdz!rEToT==#kh$@P|RH@g?x zU;K=(+}^+9?|vh25ZSV^J;q~Lbw}A(eTgKlMO?=<|6R_Nhy3>gwBXeC8nHs}+|)^6 zuC4e*nQwE2CEQu0%1x9=G)RjT0R2xf|2qtg2Gt4Z(@e|(1?*}j(253;IUc;ySq5WR z!wa$Kf$qFN*f>(0N^Z6t$ARU)aP7H((1RX`LdXdRnyk^s&cy;qq$7$sC`cZnhX=bb z1JDgt#z|k>UC*jfetPDSnOvUF$whb5@B6A9Vz*;^d{h&@g;pdr$qN%i03UJ4Vb}&elcb-3v;Fz}t*=IWld82Z>ft;UjD!&(4dG zQZseUr@8(5dDQXc??0}a`o^mxVPdaj@>~ksP)AbEMTJCjuMI=Tgr6T*#)^GhEQ4G4 zr}qx_&PW@ktq*mqy*Ut&)KVU^)-`_c=1qz?3X*E`cB?o)hOw^0?(NJEjmloWB>}$E0-1KtQbv?jrR9`sTruH}H>*CRo4w0zo|8Rw(R>G;*GoqHAoSwGpX)ZG|JSpT3~f%~vkkz}!zkSUkb z+SQoEdnR5|IRG`Za9uUNNz0^M_Kxe{BNWj0W94&f>UZZWY+w^sqvx#yo+)k*WHri` zm<@dY7n2rKST{Am^zRZBeh7J&hSAkwda+^4%ORjh(oYh_%tg&hgh1!dZ=_-CB3C>T zuW}hi-mF;iX$Vzpb2GaL_s%v4j0ZBVVlr4YnO^9^52a)x8~dz5eVo~SjD?svC8bpx zQQq~e3Kqov8*p@m+s?4B?G=l)*HwOQo&K?<_?1-C4 zG~y?0e7r#yZ<;<{MW~V{R+whol)C((?xg?803()~T?mW$^9F>43^hg#H5w(j)No+= ziQp3G#Cf5vI1aNcY@6#SyXQP{+WO*F*}TAHx#PwDbgL?240OKNXAF{ic;#xc9a=ST zRS@+fbLR14*m;iJkKt#dx{=(TqJE)wk%lgetqSg+N+SR3o^1Yb$1)D zMqMGbc1T^e!v$@i?i8nge(IKT{VeoF#UBXi!Jo{RJ1J-`AI{15e$lp1{Rf_?zCnpw zIGWbKeR9^MDs#(MeGxshy>NGiW5zYnzhy(#UnM7R>v)ylw#0NQSGjRe!!iu0^$=Xq zHW-izRxO{N+`F?z(Bt#!-MQi1Mjzz*_AcHM!5ouVg`D)BYH6M?@Dv!%~@GR{^(JVzi?EQ#A7R#WG zkb5933s+Daii^%^(1a4>a%Hi3l^gi-yk(;kjJhOZ+9YGxEg$pz_Jc_ z>BtoV=2eTc@$lc%%IW(0a?exP;aOS>5)QnQka$@EN1NabF7FC6HCCT`b;wrWq0mo7 z{}(p4LX@U^%BnxR6Rmkq8g;!&!vNNSwA>#u+digV7iI&qvi9?zccAk9a0&LJb7|Zk zLaeWNV2xxdLwKcGXu{852c(h#D_8OShUsN&K$zjJk4K!_a4lJ zOI(dm?Wx>oO%M}@%m~*mc-Jd#KOjGo2m91CF4=kBk%vC!&Jfd)9{uz=$OR|Lb#*bB zB@&N%BeXWKyH}XdG#4WJEA81WqHL~@P z<@u)Y@j`Zfp@=M_K8jnDE!DEj+tlZn^U}s zZN1ssyY|2c*(jUl&7bRy(rVSKlu4Myvh8cHnepMtMz)xD#mva079E9L;df`Jgcq7r zRk)1Fw%jw!$1=<&c*#Yf?E}uBVOf(f??iOr?Nlr^z}e$~7XHWpDS*^It-aH2gw#Md z(#y`KehOl>d8asUZ91L6#T%@EJjn2jqZ9DSruFxo7$fd zZDgq-JVjsAZC2l#j#uC6UcP$SyQZ!ZA58ogJ%&dK*DMaN&fOj4GJ2a_e!(cZXhDS^ ziA<@iAGd+$YfW2YSZ${-z(cNrLa0*c&W}zd&2cs~N+yq6kW{5_c7YyPUU1>J;p}1& zb;20*PeYHub4Cbq{9GH-*lX~_id6LuF5L0}<45UtIphuD_OY*t4z>%PeJi;XdiBrc z1TT_jR44=?MNyJ8C7w6Zl1kE*d*)-6cfl=fJtXT)(eQVRhlA&>(%ughcgj(lb%fiYa5*M{ zy0gQt7{qgx5dJRikc@j*uKLn525V4A#1E?m?1&Kk)}QfNj2XGfR<6;FT~6LCTo?9G zxsV7kjMj_0K>U^dw`N9{1^)(t*DFm-(%P^6`J2ePKho`;yrD43 z!cTCfh7JCgb!Y4(HZC*Bf6{szFB@@t=}(O0`z41+zHd|-sc!zRI+i-_Fy4;BPq#LW zQiKPhVHZ4#)OLA$5|+k0C$vv1sXAk)ye||zklZYuCUAUKE8!QIuMd8f}^sN86R{ySwpbG31aco^EM0U2oW!HgbHc zaw8|-=9mE%{J8JdmX|Z~m?`NJ#|_a>x_>x%^H02utP|LYZfGChl55#D^OlY3|M^Ja z({Z}}&5sXhk}muOvtS028$KQ9oDx1C+q%THWj55o01Jihif32{BJFKhbfg zc8%Oo>_s^ITHHJOwA=kU7p->9DG5ewEJ`NrhBp{IQ%mzhgr9G+A(zSkLv2PLL;MQVWgR`+q!Rq{d+U{njA{Pn_C;T# z>Q;o5jz?Zsni$6gfS#M1Mw2xGGI6HYNg%j`+g~}isPBCaV!!sK|L~&Ot*s;mxkTKt zYpPeG6{qR#HoDKfCqxmt4k@KEW;369j}p+v2lukLpJyNDmoIAK&|w}I%!m?6Bj$uq z+vUD#|FT28e5S1m*arB!BB)Oxy6MK{GiS@BT2{#g#ed4qqlQ5sraIgs0YE4MH^ zube=uVb}n60_x~vCXE=;XKc6xg-f$9L&6GZ1|yg~Kj1xz=ImH*`Uqc$jziFwe_*m> z;d$z>8isdr@!|Lc8sSMZ|2sBNpJ~pP9@g_F0?Mt0fT{Lo+n(2Mrfq1HjsJx)=pCBd z0RTG|O}6OxaT|cS=LK-#59W+8Hgg{=FC=85wxAY`HN9290eUdI$a5LbQndhDE?AcQw|flE-P89F7bShPT$SLy%?Dx!~% ztr^5qcph=crO&V0jTC`}H_(_LFyDH`!A;bUTF}px%x_HvB|6ITxENf^ES=<@Ouy9L z;QXmWsqaYApb6%XXxdG6QfaKVC<)EOq;xlm$5b;Zz*C|ifUa~WO$>+`ey?)&m%a>$ zgXlRS%rLw)i9E1G?j`%av|Q`N9#c5RW?Vi_i+$M*`O3dU5*;HWHjF!(rhLe?iY*R; zk(MHcc&DWrnQe1WzMH|oM1jFedXi`9!qX7@2$dwTSpXM>(VU`%x)|*LJ->2lWeszu zTF+B1&ArN^p^<8aJc~nkbwH4UHTZ|uT_ra|d3Z(x=mIn}!8Fu~90oZO^*+A>ARAie zmi-XGy-OB6ff)P?n{j)WTpybZxt^6ma~wU19-xjyed#UDx@B6Yo4C}gSmW{SBq=zD zajF`19Z+PCj+pxZAe)&QFsYpU1eQ}Dot=%9-U*|?&JLW$O5gwhq9K_A!gN$|71G$K zvQd#RVd|=wk$TQFaifHHIWp_=wVd4J+;0|U13zE$ub(dVtWAN}QCHc4el;`9kV`Pb zubWIB_lD*t(aFB=hTC?7ESf#^WwbnMOO=?47HAr{JY<1xRMY~^zJ|WdR58P#i#^GP zt3hO1(gmTqjA?JMe$}QcL!8dn&a{%%_0AL1dWb%QmmWSzJNkThd04>Z*f(kq@$&U> zXs02}G5wOD^v})1%OiAIIEA~=*)7b#@kh+F-@tU)C-WeJ_nQXu&DMVI61g7#z_-X3 z;PKyp=gf=^xGS99@Jfk*VJt35_WY zvRoHK>EcRglMSf3wmw-VnzahoU$Q9M1f0q|PJHyyx_9;GKP#C*RiKh<#! z2l0g6?&1(<=qiS>3$&>9l$I#@l*Wbi78uBNiqM zz8yR4ODywxO>NKKBsh+fgIPU0E;ClhEnxAD&HGH^Cu(Pl- z!rWv@Ce}uW&>?y=RG{QItxTz0YG^xLXzVj!qzSM#Q@xT1fVvkJ#vfJ)04x_?`U7W| z+wBk8*{?czQ`rTm(NtRMxh85xJ)nXGg;6tVIxh^MXf)}==&6eay3_C~702F9M?G1< z&dzGB?H!|=j*fPDYf_DWXs}Wxg8cS|Tx>^>2piB7EfDtKL7pYKlUAyS#N| zdB$o~%%@cA{XmxNgEtm2xG$0_nC5--d-0!Iq9w9!VjFe4{JV8Iyg7G#8Zsrc&;h)< zGt~)b#81{SIi$|QCb&}TjYEjaE5V54=-wEfv%~XO_<5*dWU#ZG`YgV+%v4M z8qWE;ND4P!7^5#KXJ*8|FL|t=ld*!U;B};%fl?UenR=Bz>t+^aw7~_GoD;f0WlT4% zc^6c)rA>`Jdam1>|B#Njtn#!t?;cY^i@+~cIDeaAJ0V$p7GEnx$hGpEu;l*Y=F^5^ z^)S0vp5;;ECgaJRg{?L9i#O@;=`1Wp+M*nXMkJofZ(y)}i$j#TcHL{zKTx9yBqCM# zg#ea``~9jYD(N>6lSs@=w~(K5F%Q&X?{MlLc^2r~W6uxeSnaFC7!d7dKE zsFF{vl^7*qyrY+lBH9S%mkQhLaOor?DwI@=+VLtT(H4y!0t3QXL}*KmCO zwu^gvMvG6FzrZQ3M$@7qxXNqk4Yb0tO8NRjc>yGWvO0c*V-F+r4l>r1y5Vh=AX&VQPmoeKU&ZyH19(twlV%Qg<$LJ) zr5$n>0^iKucbl$)&|B;HQKSr00F=Vx5{)3=3apOJ z#VdZ>u)74pup2ZF<VewinCDsF(LN#_GPfv5+*^4T_t6>MZ5mv&v++qUs&?&Kl_z(W+ndB-|7~lx zVpW@3vaAcX&em~fyX%hD1$rL>0)mZsdEr=PeN>=cz`XA97W@-Q=Z2EJH1qx)fV={d zV5iCa+O0|bw15@RRG@BP%?K63q829ZxPPr(pjA5BH ziZqmdsM#S0pr8}PX#~lZ57O1x@!l|c$m%V=^`RAmcs*`P+uv{%WvQsle`lD zGUrmX8C@0=*n!SU$gm5FN2duhO0u3#8yBKusq8ddkscMNzh$fX-Qso+3by}d zVWm2g-#>T+27%xyO8rVQcZR;(OX2xpGt27MjB?i z^b5G=rWepgUA(u{C77wg(+eOVc+D$x5g7`Qp+iu|t7=4}1zLUiIal%Jf}`6X=mk9- zmU4;?rKg$+#e+)#mW2^tn2TnOcX9g-u+Rz#9@UP!4*q!SscZ%T!iMNEb5Mo{7OT9t z*%kPG{1VHas2K`xmU3TnJh#*;@XqDCdQu%Bw`a*Cvix84%2i<&nRq=%Z^Kn+GA}|k zSd~)eT(%MWVdFj6u#Hd>b3uJ_-+6NF_UEDLFE?2-IqP<-@8|M6;a_D{V)N{-He9>!@OB z&4_DYpux=LmbpF9Emto-Mjo*wEKPO=rRky_oPu_Kffc26QIFIi&|__iJo&4YWW(B-;7P7(5z%LD(mczu0J7JyS7U*MHxIR9E$0CF0#X6x;Sb--xOf}WwLDWg+xm3pqsbTp$8Sj086s-r zdw&CwWjG_!&{7cB)64mS-fCzFZJs{ zD|4BTWawq43gkJ=l)g!hQHu5(ZHJkeT65!)C3>rbV}m#G+exMBD-SkCirX89w8*6b zEe`(uA@F#%PPv#f8xyQJy0`G?d2II&BL3DZc;DOG^S?Bke*>bXLtgTfPt>nOZn!)C z)Xk)SWqT{1BaTck7$V_Vw_8|qA^mmISsyVM4c$WR*{0n=o?%XcH_Ab?q=4qaC z_e3$ZfJftv>eHcICjD$2iRNo@<1t7F>Svn@#1^>hGiCF=Te^N9lX%YixmrXoi;?rP z4Qwt{c+96*^Pxs6-)7rM{H(b2tMsN_rM!q@b?<8vbg~8|VYa+I)*(m+Swj4V_rwc- z6Ue2o1`FZ$;T!S06QlQ(RhA->5gIO&3|Ew<*KZk=J&g$Ja8rwU_wFY`M$vdS0GA+M zLsmO-?ys!kH5oVo+3)5a1{*H#nQaj-IHLdqe1@j8*vbKV`_V7??Ux-aaBYDtk7#e7E4v zpx430g>kZ{?yz$!+ObGn!rm?59$w@k#J5m%WG#G4u>H&tw~RjLHE!M6^+J@*6^*M( zGwc91!gM@Rm-Mp&JQ$T^@~UHLj6I+P^u)DC8IA!#&!WZV0Co`I;%3+hJ~1s}xTRcT z5R#T__G8-P@usd6lx>`S=$$!OlpxM#E#@CdK$!^1E^f5qDcmJ=Sx#X9XcrX9rz`u= zD*4>IoDj-`z<`Gvcdk`+-eTI3efLL3F8Xe@Wdg6bJbgAv?VaE%U6zEhmxiqJqZ~h6 zjKpB0n6?}=1H{k6{8&>ViW(zh)r5%;b<-7RiQ;H6prSB_u2Mvs)_n+2@0+8K;j zIHKR1kh3gmaq2yHl!7-22jB5W4vTJRq_~FrXeI<-8tqvb5|Pb3+nzVM51*ou6yLxL zYi)Q_dyF9!pr`ds4X?3ew|g*j%`7WqcAOKJ3E?oId_Hux!9V;Bm`|jmNQ3iiH#LS* z0g1ACkESXf)F<}KJJp)Y35M~?C|&AKePu<@`-6#T zl?s^hUNb)ce;%20s*Ekrc^)-&i-Br96aZcrz$;8M7e@8LY59a{G!+^cwNGtd7&`@S z0Wc_x1GH@1ApTcIRzo%-(cDVHiUbCL`!S|lf>gSA6NZhbkgG`oeKO+| zJktN*40ec`6}KJG8C8GRqm++rB_7K5|7e2QKneT;AcPcfj)p1hY>c4MSoJWe=L@+Q zRX-z|Q9bl!(=;W38!}7e6$beF|aP?5qHayIX6Bx-Jh7Q()%Xf`235{4w+l{4Brw-qo;+foq0~zajz& zmTAv>sSchr&e6qnvQa*EnUVM^(-;pM$QpXdorZMznIgJ7_po2>Z*Qo3Fj%|IU;Q`O z;bPv&v(lljWuuY=BGd*>02dG za5nu18yk4FvR#T|ErU3a1KBh-xDF6jo|X{<;pM|=f*Fp6JZ8mAs`k_vMgLoN6+^mv z6>y6|bX-g|$cl17e$J_suG6t$J*ib;8kk6-e_@EC>&jwtW`4-F43h5d6n@645}#eb zFvz{kSOK|AQJ7Ihz+b#FJ%l+$XtS9%kQ)tYRUyyg%;l8tDau|wQ~uDbgK6JEC49AP zuCAxV%?d7q{m4Ere`9`LLc^^5dJL5G>&?(J&Rc9N69k9%$%fr|g1gD_@du*UaP{m1 zEo0RjAvPAP>>v0&+2*DopI_41d3Ex8H0g+$zD&y(1QVj^=X!HTa+V*Hs~~t?T+iCj zMuxoD9ufaO##5$B6;FZ|xJl|&ndMYDhuWaMig=udmsvY|3S|Ij#hD@3zQ(~Vtxhr4 zI1L*WU2z%n@^z5kKk({$YFNor2djrRMF- z3eO3dcJ3+9c&WQjyEJFIhqS?2)A^AYX1d&<1YYP#p*KqDTVygqh7mg8$>4d!n79Xt zptzBsyOp`oiv7~8f77A{c~+s0Nm4SUT-)TCHGEQ|`gy;N<@$uXcKYvE(F#wYb~7b> z=7%=}Z*5tdgW9MDeo4A6Q>;j@u2wyUn~d$Tg67Vbq#Jh7)8iS1tgdO7zNPZq57 zxYh9fOa%|!Y=Av?u0s~*>?0v_!)=|R8bdtXZJZI6#+M zMAVb!GdA%nq8Z`!eU^hKzN54v z0fK@4a|F#T>miO2u?O9(`w^a%#dmEhgPm$@9&$fs9M)iaEe#ez;!dmx2 ztCK;_!U(lXse`@a>~x6a#J4w381_xR=&!~da4(ye(zC=MU2vvvFXdo+Q_1zbFOS7Cxt_FDGrJsn45353RDKU6wz3UjU^KNP|jsr7FVvWwTwNeH1Q&^R=koqXP?Y&`_$gb3GBd_n1u($>dFF`o~THfaD9n&G43mW(k*A=Z02 zWfofca@97Id%89jvOeM?bhGWRY~3SbYa+{Wd09|fvORwlQnK1(__G1mditmW@&I;I zIzcNq>*D1btW7Jb$GXkXEr1Rdwy`B{@@;wfF za@#}?3Bh4f%ZAW-htg5YC_F=h%amPnRSdtn#vd2XaL<@o7Ix9k;40=4zq>LJNu!V| zmh*-&Y^KeV0WH0<$xP68m3}G6xS{2GKY9d@2w~BerPXAq5-HDiQIgNl2@@<@YwMOl zD(xX?&CE*m8R+j}${3Q3k#fdu$mS4xX`IbKSpbS4o;m)Id_y*0kLAJ9rCv)Tbiiu) z1B8Zg3@bB}A2XBjC{t-%Ht{?{=;xq0$vNnF&zr2my||Zhx%SOB!3^#laX5c4f1sPM zk7_N&`{-{H(o7z3A?kZSYC9BGyT>2vpv2w6n5y53IV7ze1Q`M4WqiBF%IE@GA2d_H zN;g;Y35SmcGco-SMO}xfT^_YpD|p{7W~pNcojrCVyH}Xt6M#cZHda!-dv4}2yzCIu z=8Hm5DaFOSD6DU$DDD8%0m;bON6L%k=mj7Kx1wmzeA36MUgtTcA<6iS1!M|H9i5Z7CiD*d)|N7D| zF5KQ69s7-}(d}SO0HY(<{D(J6M12lvMnv~)quZ87gB-*6s0Sy|;ZcgJy1p4{M`5Xr zWBnPmNlMR}(B3t5s)F88e~&@5gqTIEj=a4QB2Xqdxe}4S+z~L42El_;9z##?rrYQd zGzY(==e(QVQT&dLCn`_Ue5C{Oj2nwDwVzIvMX;vWoo!~HM56spMxO3_(R9MOi0A~jBc-uSo-@#Si5e8V-W)z2X&Ba-4xJ4_Y#d7Y zR9G6MXUTwUFN?n29o*}A73Op;&s0xT8duJ-%OzO2C?k?WQV7EUtjNiR0K}9uS-td_ zh2x3ggW=BOU293`4#=~&Rck?~CW8G@H0S?f>8rz-(A;p?Ru{Jem?iP&*z-; z(ROu}WLdxY^-x?R8oDdkR-%|_lyqe=i%a>&>hFc4g*RQbzdb~@90Cf$LXxcx`BT$7 zYvRXe2c+Z5Iz?UGSwt`|2wEwsP|V%3wi?yP9gaSJ8$T-hQd9cHJm2XA;O>pHsKIJ7 zFj5ixk7YpW6%20yPt<(!HOggXZ&+)2#B>M=&~5iVZ@OZ`aBq;8r8!N#it}<|U4sh( zp3v1d36C<3dDs90seXK@ciPi{d7Q!eMYR9ut<1UY3~$4#=-jnHghs9C)$z;b0Gfq#uV|SY@G7ex1_>$stccCaC4smJpIIvN zX?~Ue$^($gXQMB&!d7X|?-_{ar+a8ON4Id$YwDW_QXWKD>9cp7-|scy=E^G8`Pixt zY0AFFav~Vb$-O#z>){?v)&-zypd2BN|L5JG4XLtE;Yw#=@b6o?shWTp4fsM+#3T8J zFc`Gt7$%&SI!OA#1#-^eS<$CUg14;qHA=9hB6eR7|$edHnhVyW^K zpT;NOSx(HQ?(Eso`+)OEO9Tx8;H}&AKpdJzPmlaLWbdH_bcKWd;{l#T38WK|tJ)aT z$+aE~q4_!iig_`rAfYo_r3QcXmRqpP7zPtAKRH^{$RDL`6Ra%elUCgvw$5Je zUM8FQ6Lp_}-``h@OGqxH@Mlc~zAYkeC?+ddcaZLX#2wljJo6C$pcVSIvS!rG@Jo(e z1F#(TP&rgAL-70BWe8;o$d3>tMj z>XH5XAXdS@pF{^hBX4D%%8y@Sp)l+C^~WC>R22PH5ACmXY@r`uYF~M3F4Oc*EkjQ5 zEM~=q^t52@2fhJ7%dX}FWhV3E>~(drltO{>nYmzRLTK$AXa0cS>V?v+QE{S{PciMvJUO~i zvt8Mc{e7jS!Y%vm28umfe*RIxp7O1+ELWf@CTp`~y9N74sL}2PxowJG+39}|B+Ms? z1S-uGKH##zWX;DWxoNEoLhBdJb|0l!6{&yzE2C_EK<{Pzb>{r5eQg3x6*L(GHi!Xn zXjHab?s1Pjx(NlJ2srcV6%Uq=d%mJ%BBkxP3#CS=>(z+ z?l-Nzw27I(ZI;%gr`ZPoGOZ{%=rB%i{J;#F`fc9zSDay+@Wp&(;SZ(KBHQtd{rW~Q zxOiURO#K7?IPe0X;DbI+Yt?o^k$~(Y#(7+0vnaQP9{GBAc7JPhfAls*R&y+x$X0Xw ztD*XoLEqI18TM?ol1{N&Ga%lpzHiMn$+i-B`H{z)4{OP$TUha`we+{w#UVj?XY5H@)oyY$RV!8f9O*7o3Xn6Ye66iUxs7pWGl51*4!N&|+~EJH=K?@O zIF|kIOggu`J?l)HBS(9ogB1xyXJ(;6`j&>XWpv_Tme0t*~42TLqRTOQj&?ow>H)%{H zo4b%Vq>%*Z({1GCz2dHhAXcgA`uzl@(bNB0O2}(yHST`xC8T)D93}rZVz*AAJVB~~ zbv{kLI5H)@2bt;JzJRxpQ)hivP`_~mtU`K)q6L~8U0>6iL!gDkrjW=nE7wh--x_Ca zt`)$spK<3He@eW&;Ev|%_iAK|`{91iGra*J!6W0gvRzD$b9c1E0IoaXTs+xkWPvnL zG;K%E;fL4EOl--)_aR5fDKn|BI9?Ee{T~pIEr6s^+x{aN!SlSZ&qJertR2|=4Vi&@3=vxcXyGyzz*bdZE$J1Oh<8C3TMH?H;dNa*#5|ev4i^P%8-93>lc6o z-bT7rzq2&cnUP{$$~SqhXC5At^}RYvlr;r+7VV*wGSQO?H|?FGmICX2HI7rUq!{M0 zU!-=QH-;9-W^$HQGhy6c0pgfKMeRp7OIzzGE9c^2%I3^LyuW^(;EtAx4 zJh1ZYAZTiFY&Xk#Zti1Bmk{SzU-f$1p*C?n6LRL+(i?Mu&3Tq3G0h>E*Y1n{h=8SQf8rtaw#uy*CZd(S*04TpV~O< zdGvAO1OCutr%Ka*M=A_89H0lk`X_|rvm;al8!n@>KCJeCccd0d53yF70X&|bv@E8r z1#Tb@Zk8o#S9aeU<1e57Rr^_j>WOYy!}-xAqVggpCrs9KcO+Paxd3Ys#V_NMNgKL54(R;hz>ScXb*B+iq?xWuY?N-Tq915 z5Q6Qw{au|!ddu7+N4_?|eW1dQ31`rSo}5SUazAxB4DdHEY1)y5@y2fLml|}Ss6~}j z(L^DmDITXhZeZ6j%nXaa|8Z-S>6RpJ!7%E}ZkH9zaTJ<=l;2)QIbZ;b!$2csg*V$}vW<&KG2zIq*&irM(XI zg*7?837ALDeFv9z9dY zp9`oB`h40R&0$fPfmj#H5_$D`0S=SkmXeWOQY&YxF11LtudV>@tLbSYXs=2!+Hv^} zdj-DY7|0pV&eEU7@_G36dk?4q?*;oQR>e3%y?X6?K5N#L1ro>)e_Sq{(@Kjop-Sm! zgh0%Fe{7{L-$8{z&F{yPLQ=okJltY7qW3#teZX*)=Z1enTBxK3XuwOyjPd@C_YZ9! zFmVPv5p60ERhRWJlS2s|F|tCX6URu}>+Nid>uun3)jm;C1T^H6wl|o#BuK;r2a%BQ znhc2?`sx+ml`2doxjl63njNWI$b+u+D}Rc<9#mkBksoChx%{6H@Dp5(ESK~=6{~|| z+HJ{r{$Ev1Cb{2Hp>u1uQToX3eJgC^QQNir0a5P|Q_bBB&S-h4n134?r1*FKgFc}{ zGV)~1cTA*9lK_)pYK!$Bz23TP=mR{@#h)_oF?9L&1T)@Gp`xigcRD?40=KIA~Juea)1jKFU&d&{MBFUCI8P97;3mdg`k2 zQhppIC>OD=z39o4-;u8gF-M0^h9(9?;3s6-wDi)n6924G%C%kaR_=A*>WmH7{^pra zuijF{&)DPnef-eiI2cN{(@JAC|Jx;UC@ji$WOk4y1-;>{zcTZvZXK9WKYB)OP42MW zZ$15+ogR6u8U`u<%1WS_g7Y`pTdIcMV#V!cJc5VufC=bgYryiLFa8-}fRk#)j2U@p zk$3?Rwoh&MM1|eTMmlyXi3a&V`!tDFiYn^`6pFZcZ zI~A6z@SRIWm00#1v~;F*d!n98p{Q^atXEk+^*UpPRaz@4d2CMwJ-=R+YVi(@=dg*& z3*v8OZoagPrh-nMDlQ+<%k4^+~T`F94sCzPdc_owGSF9BjD&6gVAo0B`LE=47Wh<S1 zcHO_pqj}e+@!`31>G%bJ;4PI*{!(rqdz6i}zX0fTdj1g8X+F)i$y4gaK1Sj$0H;aR zP)h7rII?%wIc;~oM1JN1K!uf?*Vm6|kIoBpMeBR=lA%NJzQ6w@n_*Ft5h2;-TCtD{ zHEBbH((kjFlEA%3ZsnZSW)f1uTdyrVAC&`Q-|I#A<)4I)ClwKbfWsaH6zNR0X)ZFLu8A=p z1^2nPyy=t}qSs4{Le#2Djd1$;E0`dpt-Q!G)+i4PYsJ@X!=wDW6HMz*0vT?-M*9#% zeyG6o0_99ALef7`&l`sK ztma!;{1YWW-u4C^&d1$~>J$(X@N2PslTR>iG=gW|Hn!EDO8c*s5f$*-EBqnvcKHcc zxdC;pTaP}OWOqx&l;Jfu5H`EYKOc)8^R>fU2Pluf{^Oeny{qQ#l*f|9G?0o{mx8Tm zvsah+;XRO{873v1<`9z%{@-f3kl7kfE`4{*%=m3D6ap6Dd~K8?uwQLkA0}H{u%vr! zTU~bK0ze5;c^j0F4(2-ElXwn&%3of&)*7^ohdRX?bqft_z03~k;9;Jg304;TK&@u> z`Xf&8R+b(G&T^a=1@dEr=>2RWRHODNjVm_)1gyi8j(-~das8wYj(;^N0d^U@CokDQ zeXE$vV=^*s|G^A9nBZ4O8D1H)9|*4Bp|mbu36Phcj|-jT6Mx;ua(kg;InLBoG+tyo zraKBse}{R&Ur}6VSSJ^%coZqKc`vZ1%NTft=vtn;jr)3;=NIBerOk z)XR9Ny3)U#`vseHN->IMPIkR+3jl~HJm-^q!S2&r*SCI>uEWrLzjFIt0L!E*IWSM7 z=KeOXEr7|dq(8N8vf99sT}E~9QiN~65{HR63}@w~huz)JGfGtWNX9|U13X9JJlHEy zgj`O+m0jMorW!mI`RN2(5uUzVFv}bisfh%04@+%_K8^&mb$q znq2*k3rRmF<2D9$>60@(7-5fJmKhi`-xHuUV#{JmD9_V{VFie2LZkGV|2~CEkaN|+fqurm$D3*>m4Y=lr#qusg{TffFnLk5(~@I zA!5wk`R}JoSlr}@lI!3fwc!`&V~|<#mQX`W%8Th+#h!`bu<1}ao!gOT36NCG%m;N2 z-!o$K{NOFVErVz6bL z;B_dFpoK)QFz~>vV@jZnos-r}vd+YU-1PtVjW`!{=iD+Cc?QR>{n!fs=C6lW7HyMk zqBJRuT5Q!cH$3%X1HT=d#glXk$rueO&_edE z`h@kjyc|gI2jlYJ(90WJ>Y?I{%OXJiGa&N;72s~e)G<%!##B4WK7IV)c0m#RG458p z$uIkTQ6-j8k1dp>q%5?|T>DKxh{CIwr8qNAaxc#TX+AWMw=%+e5;*xyMwdfB6!j#i za3K*L)QP$P&}uI1<8Z3b0Jn%A9WW7xer!sPwVYS0ePh)>(L3f=ZeE!X*wIsCYC%D( zaG6!87rjUw?iq3OH=n)_^ZAz_b`oMQ0gYAynX%W9WbOl7OFw7FVa^qMmE4Q%T1* z^%{J5`iEhz!TYyh*^I9U6-L z{ZA4CJ*jc(#SN`f)FkhCjz<)9zE&D6PAR6DL+gcX2Gh%LEp}lOp_uY$@uBW?PP2#k z#no2^*U{0+md23D6eHlokY!#}y_#6iuP+GWLmPv}1#t~t*E@lBj`kz9Aj{n?grRa&ekQa}RIUu&J=2QN1 zZjinqi)#5posZw5UxNZH=x~xhw1lLqOjCa(YAw&E@%GWA+#@pPzZJiXXL2bAqSQPZ z-@I%3F+g8li+Z?j`eYW}#QMyd?xSR6p{*bV%y_eG7UdK~4jI0hT0hP3-r<3mMg1!SYx3tRFr^~lp%-kNPy-N!O8GgCELXS^%=C4MdaIZ7UrYZKJluSEo|)zXcj6$l8e6n$#n)O(j!ex~_=exusWN`(?my#OnO7T?O& z4A_PRIem0`J>3W%jd=JCDpD`nGP*51x()%sdc){W3VOe)?oGThmF~6(Ab;2-{Q;-j zeV5z<>FTG0;8|$53h=TZWOJg*0TH}zSS4kTjiBWQGJACj{M#@==tvM8jLpp5qbo~p zJfM1x=5o2O50p+-y73*NSXMEi3Zc(Yn`nXI?+%(WeR-ji&M$G1nA~@X zK(J8S-|81jQVrQN4RDLIq!;JB{wycl@{aC@Trzc|5qufcXHI2%31J4JZ)l54oy<}F zC9`yH67nD zv1G@Ji1@V6eYc*#jP~|H?XwQlq=?PY*8)LF*!EY;AtnJfv7y$N&A7@Z4&tD$_uj;; zn@^v*`Xk&XWa}%d(-$Dxf%e zyETOT)OnKvj2`bVQlwFB(@d%PJQc)TV9CF>Gh|j@>N9|nu>0U}`mWfKpmi%_0d=as z_&b3{Ki*J3Kb4=!U3JJ+&B{1}wv6h3e9RCi|Ic-FHs=IfSy#68c(P6>b)POd30glpjM>Vcnxkr&DMp$(-uMdAyMfWQ z@$JER__mUP$CUMA_=H?w*=JV|vHn+UEjN}@yQ^mf<)tS<3K@UvjYOo}{7ksh4c_~l zAq}Z%0sfXpO{zm#2O^1zQ*t7zUBMFumcz{+Lt&lox{Glw7G-P10G6J@5qB@9P_`w} zme0*6w|ihBPdoQrbAH`YYkRLi40G4h+>=snV z?ELx0w2?p=qMYti_GsB4Pv&GdM96Of@9R#5;K^m;>}<6b;#hi5S|hqPuX9H?4eK>3gtl2YDOu-^M|ExzgT)%Q}A=Y&n%gO{C+^z;cUVKE*XG6}y@bn{}k;2(JfeyyTIbNVEVv(gxmw@Q2 zG>>R$3MGOrXAXSPXvMvW9gBXs8b)qdvh&VsWThb{D6&1hE+DWcnZ=)B87?EVOmC|w`%;V;eH zyY5kR^rD%4W3;Y$ZqNg8sRyOMul@1~Ko6yq9;*kt`iDh_=cd4iv~GGs1}mPQ9}6^N?q}V( zvH`qmX5i98(4G-+$qiiJzXBQ)ICPo}YujwFMZ}xmWZB!ki}b9hz{sW+ zGF(O$o`CEiF~c-D5!ze+;GPl~gOwH&{Nbnr9}A)? z;LguS0M}u(416L#k~H!(p+)QdWD)GX1tQ5bUdF?z7l6)%3&2^GD7Ml;fpY~n?zd%jA6YA)iso>&XeVA>;n-LblVM=fov&dK&_4LtG_>w+XScx6`;ShTX8I?00&D^ItPPic4OeN7-uw2%ISTXY!^^@stYfeKCEe|6 zNxAa}SRt~LW%w^U^D#S^rP`+-)cw5>OGXLZbTF2DCKOi*zy2)dEmhH^<}f+?Eglit zCMm6_6p9y5yEmI6ozH6AUC}1`q+Q_luQ(a09|qSBll`c?@jY1aliLlKEH0@do;*;w z(=%9M=^Xy~yCy=mUR#&1=qBGwghNRueW`*|rcVuH2@`izB;YN8os~aF+#ppHPdPNl`HN~yrkYv^Y*2n{HIH(^N>q`O@z2nGH^pgrHs_iTK&bh|7v$$v+s zoegkx=$>QheT~Y2%b6DWzdT?q3zf|wQC%%0=zB}R4Y$M_oEvfE@d3HR&n$D{QHWIy z%(1Nm4`@8~g&%+sOeoF1?ccFn=xtVxwEucD9zfd3a!|46 z2PZR{4XbN6rk>~9o&BTUU#EeTJ+{3^K0nv*_YKQwIGQBiRyZrf93kGQCQV4%Q}Oifh28YuV}TB zoRzpm<2!;ozW~rzsF{K;kR%WN%1_B%ztjlqa_&}?(isN)08{_~#QQhP7OelvFxF0a zv2ZeO#%a%giV!B$;a`1w0Jw7Jvd5>X*@1LE-Dujx8sJMaj*#?uv~6YJ+e`m5GIK(G zM8N5^uNryXXk3CA?R9!P?y^(z{d z124x1aZ0Sl!sYpAqT3BW%P4z?|5LpH=n;!I0U!KmWHdkB@YR%B@CF@sgGsbD&iJSaq{$s2&I^VHZY=SK&01fEf#BF(wky<;ZtB!6 zZK_#i^J|!D2?zR)wB9p?51BEEt8p1tSEL9~`+FjhKxlZ*!yqhQAZ1cG}wft|ob+df>8Y8Lo!s#vG`b)M;Iu=DTH3J;q zD%+wK(m|w5o4*r6hhMSCxDep`Ra~OPfL^62luOuCwo|MZn_|B)#=9@o`@PG%gpDl! z*x{y?pKNTsvX9A$cvD!^vDG|_S%?y4E~lC;F~ivU?%?3JcBwpF)-(>Fuh0Y<6d2EKwnq|yAX)+|;? zqj?c+rK0L*WTh+i1MF5wDK%T{@2aG64h?od=*gIO0Q=83X^moMX*Mrk{GH}@CiL+t z&^9xMuubA@yywSe2i}|U2|#_&3*_&kzhNEp`DLZ|-HKDgnAdP2@iIhbJd&WbX7%My zw@J2Xrlo+1wq)(R&VXB$JnH)(4^plpQBK~(!MHwS>%3o5<*7t~xHBKiZnjH@AiJto zwaY~5*mG!%W@&$w^)nEd#rpyf+J`iUH}Bh=()~+N%%)RQv3N4}95i7d*$G*p&bm;9 zdOePKC0-V`fErpr_$`lBxhuHq5EFwQxF0wwcBy353k|IVJBA;|o2)U8_^v4k+oDZR zx!j|K2UURULK=IhGT@O){N^OL-)`ehNnqvzx${11cYu9IMd$TDWzUmIGm|EpQx?1F zEoVfcMg#QF4rd}WEtUd%X_ymjQuqhH>vn2f!cr&Ma|>9H8@K?x!=|K1e@a^_b4viW z%$(AUxronq2Mw^A)!<{dsiwmS542BPk^eP)E5a3vHHU%eKU4qILXEW{FAI_jwkt{& z<3;jPm51fbLm1PmbG5w3j7nu~hB($4xLp3Re?2{AjNQh|!C%vJV9vR4Cn|uY<0yYJ zzOy(!pP=q}t2;07PGWB0EN9hJDi|KcCOyIikvp+DMm(=H|Vu!cHi<4l&|@(_g; za(~oW#?$OD;<8KlUCS7%)B<~>7UVqi%phQG<=^MOuyUXs%akR55R8_Lex7f-ghlA> zJOwR}iT3R%zO8Bcyi%dg|HkBHLRc=OqTaPbuY)L4R?oTEp@mDN7ZLIeMLcqq(UMe` z%9z;gB63@YCnQ_iPh1{Fx!)o+7-IfHs?B%5P1YA8&#@Ry$fy96FBLt)p~R6CArdBb zFe_U-kb~JFnMCLbj)|C|dFu7P3~-r`*Pu_k%RAEKzhG%mt_10gN%~--_&k3m!fzE# zH7)eBM$BPaxUDkHmPS^6z6ER4a~5yDG|wbN2AsI#2(M@NPmCjY;VjXhu4TCG)*$Bf_^GNPoAS0V-J>Yz8#C(&|F&}Xm#H;n@7)HShTZnZ#@LmT ztxnP4vv!3Vf|aZlL75qWa@8b|vb6&6)XSJ1nxSxD`;$Nb&CKP<6cW1-(M*b&!+AuZ zQ;0Zr?dH?`Q4bFfCJMB+jX26*;ZS}iKCpbOC0ZMBc(tT)-^wG0W?N}sw|K*Os-|f@ z3_PDvG`n|_r{y_#0T6?~=@Pl|mXt5R;#3WszS8-xd|jQayzqWA!zhUX_kZdv>Y@VZBHxjndG%2-8+= zIGnu(^NE^a;uQCA@e^h>(m4}t>te>_K$!iRKZev1*^_)S*laMY(~LfQ9LKdkE^i;_ zx!`-?c;3xdK$+S7WhY_Pus*)`nMWlBy{=)-fYr_IW-G+?!zrd3%)i^|M5s^-8<3r%G;l4?{rhpjXGeZhnt?RcxHjohY@} z!3@+3BU(2%_Egkhd!lu=y&*EJJMquPNi;P9iQ+s=FO`$Ayf5KUi(>ozdZf9I!TIlg ziPp^z%pHe&O_KOq81d~l0VgZd2yQUq&ojbqFVE7JB=(a&u7c;}|*q8L_nB^@J7U1a;#a%fR{tj=6uF|J6vW)EFbkos6B$YHz~3 z)0wnV7YB9IxqRkR_>nMP`QB(fqIIIwrczdGA!up}JdLh1!Hq%-g?`$k1jAG!bg{8i zHHOx*u4Wx0;2b3VhxldRoBj-9{QVS953x$_?T zGiY6UMC|tY3=ZF>s0RnWVHmqH_+@~$e6ub{O3P*8fUdXfA@R~$CB>_ds`i7w;dwn$ z)yv+t~ zt9=2;BOPt({ zIo#=l4)M#tH>aSTx=NdywVD3OjpB5hOMU0q)~QW(-TZF0A`0 z?<-UK=_^-#1Rx4^zw-~2nMuOmw#Y%W-@@`NPF~`1qP<)x!y8l)6BTeAbvfSqULM6i zx9v4HatzKnx_f+I{ycx)weMU#b<*#s-faE{A@RDRM}u<}(J#rOAkd)LehSF8%i*6$ zCuF%vv+1&F+x3-AHNUv>L-3gGkS+X~6rW)#pYc*zbOcO1X~*Q|^!Bk5`)k*OHy! zEH3ixsnF+aeNEm4Kg2wSD?|RPUPY&n`*ho8x-o4r0$kok+u~5Q8;?aHDtXhgaB>oD zR;^NEsY)AYN{fjkT)*Z#x{h+!cMZh*6Z!fbET~fP700Xr86KBN=d5gX-+UeX1lK!cF_rJD`CD0tYqZl{0`4C z@!8k`1dLMi+iUXza2$`)odlhf)S7uK!6kp)onk_1yXO}U$TyRY805#BoL89hOGA#7 zT?r(uBkvQQ$I#!@-s#Ekx`_jO8UNYi50c-PP)2Lb+?K(XYzd`Z(arsur_)MF3eU@|f`1ihMq0k}L%^}H$G+*`Uv|}f zTYn}}NF2@!>{sFpu>72*Blck}u*YfI|JbuLt3id5l9c_h%4 z@+8T=+|CoE*O6!xEkl)p=4%DXxR;T*r3&2X+eNbqqEuS zckha_hZ2z^QZ&FOdN$y2JBei#tvaY$u(A0Jv6MLLbwFHV zsTLH4wW%1WQPIW{(sZXwl5Mqm+o|JABBfDNx|{7~#74UBI2^c1cxk#-z?}XTD0MA; zPsel+%;gR5Ra8){+xze&^Wn&jkwBQPBDNE4f(tIy!pzVeK1uvd`$t%a$ftTFEuQc= zIgj}`_p{q=u?FA?NSpjBsP*Mvp=g-!fVZ=jY^}z^Y7M&#Iq}tPEdLwDwVT{I2Cjc4 zuEcZqh3G?CQU@diYiIi=S4;+fv3xKq8en&=_U~d)0J`l@Bm3!(&4hK7Ott-#^@;*( z+_-FH{S4~bZ1L?>YRp-B+23qO&HUGIO(nv@vcHkQtaw5%rj$O9d7YKYwY>m5^GLsR z1*P*@1ap#snR2ib{LG2Gd?z6J(e-mbmvpjl(xU42=@;kFAH0hIvCJl;jBVf%5GFKJ ziGte%Gl+U7%Q>tdTQoW_<3>$RBZUMJ{c07#l#*;SFoni~u2GC?$JD&yZgUA`kWeh^ z01E^qd&7L*cC*!;tChT<7(-R1Xz;UQx7N>f)O86tluz>LZVvY90?MD(0Q;pMFOO$R zF90IQ}T=_exul>9AoZ2ex zS=95jH?clSA|Nu>b8DXcN5ws?}qQIcuiV=sh=u2 zR?#K*FJA!GLT2=0b$$9#H_o|A^REq)tZq&=NN=DH-49jxN6VAB^DMZn6B*-R1%t|Q zuNk=fo8T`~EiA!$Kdp<}gas>l3l`&~k8_v_hk-IWSvBeQ8IN^bNu%`oIub{l!3;T0 zi8JqT{7aJS+q9l@lH3%T0!wq}&uQ5GBt3Q6xc94;DoZW>T#&6sm@0pc1kaTh*upV~ zKcqNHBw>C$V)+xi4K$g^T7*19NuhL+c{OhKrNe4^@S4=zfev+s0F)`Vvus%`hE8=I zhZB9VHh#vB?oKnrx6qdpIEoM545Xs`jR)21mifL=N4c2$6Hne1g{L0Q9xX1#&20q7 zJWne*;LI*lumTo{7+`{wn>hx=C$^;)<(>pT)>-+3^?2_=zQtbdLr}I(4Aj>dUOZFI zqP*rpIUOQr_xc;yYaoxE@EzPneCTw)<-hZo7LJ9r1yrPf(4_FuqLt;}{XNZTg_R%2 zTzR9k-wD)Eg2`PonWoc?-_bb_``^o2Vv-$jj~;oNf2P!}B{U%oTd+)yKelFr9FH*T zA8@kg!^NEiUF$ZW*=4(~O1nsX%qP>V@gCx>A!F{<|ADFH|ADESM_lU^Z2kX7TKRUz zG-Zi6ISk6$KuK*9KZuJ*#la?D9r%!eWAr;yNtnDG{T;g=(kM~tLE2+2!M)@30Q5%i zQoH<=&S;WH_n}qqLD=GH^^0y1YF<#CQJ{_9Vv3y6Cf;YgcWeSI?$cFk-h=yXNl@Bv z6&?Af#RuysD>x|G%{0r$4d7Vd_H=-DpML@U*YK%5fwq5H>^YE$EJx+Ah=D?wEU- z;%)%Dv}37R&nEBHLLC#IKU*GgBSc^6*1tNZDIf7anZczzt@dNjEpp>ltf2fu>}UGu zDMxE|v`41(Si+>MG}(;!2cB2dCT^gK+77}}N)0&^m7nW1YqmF_vUoznnuXQ^Cu2Pa ze1s}Cpi_~}Z?dQ0lX>-R(@kVai?GE~W7F9-C1gIrZ=4t0L1#NQ*PRLifdWDmbx%Kr z-bTavRaUv5&&l*cPqssau5H`xK7k$FG%iL;&KH@(#CJePdQ0G}3xFgnI5F=d?3{&a z^dseUmk@NhMmLwYPdqG9656|F6xGM=6Ke)A!DiXPV5GZm?5M2~)o#9jBh6)d74hM9 zpFsVJaXIYX`L^M?S^>41q~Z+iBYaKTrPps`N6b=ifyVy&P_IOA)h=h9ggH#j>g*Fw zUum`pbzY+%VNVoxK%LP<+38jhUWkB!W|#hPYRhp!!6S3)Kz5({u56+ewC)g^RT=}T zx7VHE(pEu_=!zTXDW*Yc@W(u8T4BnTIv1QDcZs31Ah+M&Fy!BJ&%n4cg_G>=k>JBw z{5L38qzEee%a-tsmS%V36JhfEjpn|1$p|@Sr zuWyY*_AZy(kC$BmEh<|#5-tG062l7W8{4DtQp;I-M+>*Z0TB6wAHrGYu~bL1uEK^Y;-!Y zP69#HpqqHxAckJQ;3!R4Cm7d?Q{L7h%|{^IYb~=v=bbGgQ?`0L9g(n%_n*4=zK5DCfH!i z2gEn)tu&K3OLxz)u!3HJ1guIK#6?kzgMhX_B5$9Ebwe?v7hkvnU_R#>J) z=1I5rV2Y|2O!9h>NT-=u|q59QKg;5yd0 zBJF-`5-UN9t7-l+5O_8-!v31;Zs%q}tg;qvEaGb|sWXm?2NZy;d$q?CN6UT1yPNsn zcjk33UDcSD-RslMrd4&7y)BH|T=lszMb3shVB4aKXPl2(CZ807Nl*z1Mmx^1|Er=OUt2Fh)#z(Quq$$t`NUo__k|^F%;4OoPws zo=Dx1;0!?X!^AyY#fq&xaVc0{U~nkA|2rHw$!6axh+@gbpqw6$S2TthGIrY=tS~Uw z9Py1z!3)$g@oM^0wK`d_y4DrH%Js=0VCLOc7W%-7T{Y3q+Vg?lkA=g`XP4I$ThQuxfjeN7)3kX=;1|+$ zyvsnkC!tYpsHM%j#X9%@1hNKA`O!Ev)cH*FS}CmB-9)0V9!C44c1^oZzuiQ!Vulq^ zjRnR`D^;~*__}1}j_t1JV@v965=m!^guL+Rju+wbg_l96%gnK^L5<6P&^l`}MOnQ^ zqsIoJCpmnMdfBwEo`QJx%{Do4jRcX8S+Cab6^jgBEO*QIM!Z^VT5U7HsoxFznQvCXwK)R{CJzU6n3<}rqj(Oojh;Nre^L7Z^4?};(=qU`};uG^HGyi z>TNU?VY$inq-2)OrN7F;JAR)6xIiW`&-TsdKUQmo6zwk7ZFrUlsKru6keiR;U5k?I zk0D$=Y^9{uW7Q?Xe9_;<>OB+17Ua{VW^CGgd1BPnocEx?Z}4^oI(vtxbhFZBjwv@c z7L|O_#KWR*Xq3{qUsCrpLq&l#_ztERMdSE&_-GifXx}hl&_f=1H8sOE&(vBjmekv& z!I$@DnZ>sPKf83ve=P*Y4FY=I&n~7);-3wjw7>|wE2}w8ecRS$3k27g)3Q8e#aMb-t%jd)9JCb z7sGYjy==Nz#WfaM@Z-Y-p#*`BR$UBXp-Kw!cW>rz+IRTig2Ag!Ew3^JQ%c}Jrn+j_a>y>dwJ{vxnuFTboY|~v7}7f_+Z;;KhY%cDX|)owpXP zq;(eCrokS#!rl2J)zu`L;4U?3JxzjXEkbaYo(;dhbRKgm_c)W$V96!b1<2#HX4$GCnpIxVhrvt}2?ZYo+dWUgA zamLZ>^?OD~j!DlA@$x&keMh6o1m`CQ?9t6>IKHK2GSJ|h>A)E7e*XZ_C2uljEnlhN zla7}gocua7Lub;rT?WiLJQ!=E8VO^YrqSot>Q<*%-yEp7*spVO!MNbbG}L1JF2{A0 z=F{WUMSMuuF>HN9qES~T!bd06Tdtd3rj9&Kwxq2Z{{VJrTK-xn%eU$A$#lRhi!|A5 zPmU|MN-l;*=gTvtREgnVj4n2&KIB(nuHh?*lQeXj;>(pa6pr`t4vYT)Q#0q%;nc3I zuuYUbw@r2M&`e_W4&{el@T?8Cq-E7*Shf00lfIZGZoY?3S`9oJY8{AW!;dmuaj>#F zu=Ng!MJFeHj!&pJeKxm4@bI?e+TkKF&}rNJh49<-@sesDL5RH!b$fO^b9E$>Pv%jg z-1VDOo*hJGml}LOk<#knq^TwoQJh~~Qz?xYeMO?l6y+xe?8(o6&_P_o$7ThxjxCR$4e%g78JT5kyGRn9;Xu4 zX(f+^B&|P~Z9Ci0!D+RTYo*eEAjSA{QY^`X9(eUmDY7k{I?I00INQpR&fT}ICT$*E zSY_8KD&X_`mXjVSu8T&^w?&1nw;pI}NVjX#C!>p+^L(8q)+i*EeF&(iMJTF88JoW0 zsJ25KK&byamir^MGyS7*RP6@R7VAE%zhp2Q*8ct0#m6+$I$C^KlSzqqWH~x^$ z4fA-?>oi{v6q}Q4f;tOYJZep+>`iT&Yrc-gsN#yKrNA*wvKi*qo@sY!n%p9vVvNyN z6^GNio(&Eu$34Zi+1Y-g(6rZ6zR2TGMTNH9OL1-5c~!tAjCy%3PU$?D?ZLkEb=D4T z@;o|hT7Tuni-8r#5>J#^qL*Ya3#zhBMHIQF$D6w;3l~C7J4T2$)v}ChgG5y%5|{u4 zA@&eHz(QG4DV}G1GC5x?fN8H3x|OoTQ-iT`2w^}03$aY{Q)SZZW1r?>R^!gx((ui$ WX~5<~^P`}@AWDnjpa. */ -#include \ No newline at end of file +#include +#include +#include +#include +#include + +namespace blt::gp +{ + + blt::expected image_crossover_t::apply(gp_program& program, const tree_t& p1, const tree_t& p2) + { + return crossover_t::apply(program, p1, p2); + } + + + tree_t image_mutation_t::apply(gp_program& program, const tree_t& p) + { + // child tree + tree_t c = p; + + auto& ops = c.get_operations(); + auto& vals = c.get_values(); + + double node_mutation_chance = per_node_mutation_chance * (1.0 / static_cast(ops.size())); + + for (blt::size_t c_node = 0; c_node < ops.size(); c_node++) + { + if (!program.get_random().choice(node_mutation_chance)) + continue; + auto selected_point = static_cast(mutation_operator::COPY); + auto choice = program.get_random().get_double(); + + for (const auto& [index, value] : blt::enumerate(mutation_operator_chances)) + { + if (index == 0) + { + if (choice <= value) + { + selected_point = static_cast(index); + break; + } + } else + { + if (choice > mutation_operator_chances[index - 1] && choice <= value) + { + selected_point = static_cast(index); + break; + } + } + } + + switch (static_cast(selected_point)) + { + case mutation_operator::EXPRESSION: + c_node += mutate_point(program, c, c_node); + break; + case mutation_operator::ADJUST: + { + // this is going to be evil >:3 + const auto& node = ops[c_node]; + if (node.is_value) + { + blt::size_t bytes_from_head = 0; + for (auto it = ops.begin() + static_cast(c_node) + 1; it != ops.end(); it++) + bytes_from_head += it->is_value ? stack_allocator::aligned_size(it->type_size) : 0; + // is a float + if (node.type_size == sizeof(float)) + { + auto& val = vals.from(bytes_from_head); + auto old = val; + val += f_literal.get_function()(); + val /= 2.0f; + if (std::isnan(val)) + val = old; + } else // is an image + { + auto& val = vals.from(bytes_from_head); + auto type = program.get_typesystem().get_type(); + auto& terminals = program.get_type_terminals(type.id()); + + // Annoying. TODO: fix all of this. + operator_id id; + do{ + id = program.get_random().select(terminals); + } while(!program.is_static(id)); + + stack_allocator stack; + + program.get_operator_info(id).function(nullptr, stack, stack); + + //auto adjustment = lit.get_function()(); + auto& adjustment = stack.from(0); + + for (const auto& [index, value] : blt::enumerate(val.rgb_data)) + { + auto old = value; + // add and normalize. + value += adjustment.rgb_data[index]; + value /= 2.0f; + if (std::isnan(value)) + value = old; + } + } + } + } + break; + case mutation_operator::FUNC: + break; + case mutation_operator::SUB_FUNC: + break; + case mutation_operator::JUMP_FUNC: + break; + case mutation_operator::COPY: + break; + case mutation_operator::END: + default: +#if BLT_DEBUG_LEVEL > 1 + BLT_ABORT("You shouldn't be able to get here!"); +#else + BLT_UNREACHABLE; +#endif + } + } + + return c; + } + +} + diff --git a/src/main.cpp b/src/main.cpp index f107706..d0a55f0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -22,10 +22,6 @@ #include #include #include -#include -#include -#include -#include #include #include "blt/gfx/renderer/resource_manager.h" #include "blt/gfx/renderer/batch_2d_renderer.h"