From 09a47235ae766546fe6ace13fb0de050dcb945b0 Mon Sep 17 00:00:00 2001 From: "chia_hong_hsu@brown.edu" Date: Wed, 23 Oct 2024 14:17:23 -0400 Subject: [PATCH 1/7] updated start working --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index c28fc87..4ebee1b 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ ./data/temp_obs + +factored_ssl +__pycache__ \ No newline at end of file From 75f491ccdf950a0c4e35dbfb2a52069b4de7f915 Mon Sep 17 00:00:00 2001 From: "chia_hong_hsu@brown.edu" Date: Wed, 23 Oct 2024 20:45:21 -0400 Subject: [PATCH 2/7] commit go dinner --- .gitignore | 3 +- configs/data_generator/config.yaml | 1 - .../__pycache__/data_augmentor.cpython-39.pyc | Bin 1474 -> 1475 bytes .../__pycache__/data_generator.cpython-39.pyc | Bin 7843 -> 7874 bytes data/data_generator.py | 51 ++---- data/temp_obs/0.jpeg | Bin 37645 -> 0 bytes data/temp_obs/0_modified.jpeg | Bin 35196 -> 0 bytes data/temp_obs/0_original.jpeg | Bin 23789 -> 0 bytes data/temp_obs/1.jpeg | Bin 23933 -> 0 bytes data/temp_obs/2.jpeg | Bin 23673 -> 0 bytes data/temp_obs/3.jpeg | Bin 23673 -> 0 bytes data/temp_obs/4.jpeg | Bin 24011 -> 0 bytes data/temp_obs/mod_img.jpeg | Bin 23849 -> 0 bytes script_gen_data.py | 151 ++++++++++++++++++ 14 files changed, 170 insertions(+), 36 deletions(-) delete mode 100644 data/temp_obs/0.jpeg delete mode 100644 data/temp_obs/0_modified.jpeg delete mode 100644 data/temp_obs/0_original.jpeg delete mode 100644 data/temp_obs/1.jpeg delete mode 100644 data/temp_obs/2.jpeg delete mode 100644 data/temp_obs/3.jpeg delete mode 100644 data/temp_obs/4.jpeg delete mode 100644 data/temp_obs/mod_img.jpeg create mode 100644 script_gen_data.py diff --git a/.gitignore b/.gitignore index 4ebee1b..36b7e37 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ ./data/temp_obs factored_ssl -__pycache__ \ No newline at end of file +__pycache__ +temp* \ No newline at end of file diff --git a/configs/data_generator/config.yaml b/configs/data_generator/config.yaml index e9fb687..b4a8b6d 100644 --- a/configs/data_generator/config.yaml +++ b/configs/data_generator/config.yaml @@ -25,7 +25,6 @@ state_attribute_types: {'agent_pos': ['coordinate_width', 'coordinate_height'], #options: [default, random, custom] reset_type: default - #options: [agent_pos: [x,y], agent_dir: [int], goal_pos: [x,y], key_pos: [x,y], door_pos: [x,y], holding_key: true/false, door_locked: true/false, door_open: true/false] #agent_dir: 0 - right, 1 - down, 2 - left, 3 - up controlled_factors: { diff --git a/data/__pycache__/data_augmentor.cpython-39.pyc b/data/__pycache__/data_augmentor.cpython-39.pyc index 2219c2ba3940d09f7ebcf77f1a1f57bb72a264da..e0a4ea01530e3364935980e14e27d1a769ac8b0a 100644 GIT binary patch delta 52 zcmX@aeVCg&k(ZZ?0SI_(B{y;xF-b-0=NBg@7U`!XmL%#Y7nkOlnCd5I6qg#CZl1=Z G!wdjd@D5f0 delta 51 zcmX@ieTbVok(ZZ?0SG3P3vA>rVv>x|4=qkDD%Q_Rtjej(%gM~scS$YIF3B(0Je^60 F831n!53>LO diff --git a/data/__pycache__/data_generator.cpython-39.pyc b/data/__pycache__/data_generator.cpython-39.pyc index b73f59ee1f320ed978aeea88b72beeb7dff17f71..862cbe3d4a09aec1d4999b35fe9f5413b5b9166f 100644 GIT binary patch literal 7874 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 literal 7843 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 diff --git a/data/data_generator.py b/data/data_generator.py index 7b323e0..9d98114 100644 --- a/data/data_generator.py +++ b/data/data_generator.py @@ -31,6 +31,14 @@ [DONE] TODO: implement (multiple) controlled environment factors at once - Random bug sometimes does not allow for factored expert state to be retrieved ''' + + +''' +[CH 10/23] Add global action dict +''' +action_list = ["left","right","forward","pickup","drop","activate","done"] + + class StochasticActionWrapper(gym.ActionWrapper): """ Add stochasticity to the actions @@ -59,12 +67,12 @@ def load_config(self, file_path): config = yaml.safe_load(file) return config - def __init__(self): + def __init__(self, config_path): super(DataGenerator, self).__init__() # Parse yaml file parameters for data generator - configs = self.load_config(os.path.join(os.path.dirname(__file__), '../configs/data_generator/config.yaml')) + configs = self.load_config(os.path.join(config_path)) # Configs from the yaml file self.observation_type = configs['observation_space'] @@ -137,8 +145,6 @@ def _create_observation_space(self, state_attribute_types): return gym.spaces.Box(low=min_values, high=max_values, dtype=int) - - elif self.observation_type == 'factored': raise NotImplementedError('ERROR: to be implemented after factored representation encoder') @@ -209,7 +215,6 @@ def reset(self, seed=None): elif self.reset_type == 'random': self._randomize_reset() - frame = self.env.render() #add the visual observation before augmentation for debugging info['original_obs'] = frame @@ -229,21 +234,11 @@ def reset(self, seed=None): info['state_dict'] = state state = [item for sublist in state.values() for item in (sublist if isinstance(sublist, tuple) else [sublist])] - - observation = self._get_obs(image = frame, state = state, factored = factored) - - return observation, info - - - - - - def _factorize_obs(self, observation): #TODO: implement inference time call to factored representation model return None @@ -298,10 +293,8 @@ def _get_obs(self, image=None, state=None, factored=None): if __name__ == '__main__': - pdb.set_trace() - - data_generator = DataGenerator() - + # pdb.set_trace() + data_generator = DataGenerator(config_path='../configs/data_generator/config.yaml') MAX_STEPS = 5 temp_dir = os.path.relpath('./temp_obs') @@ -311,29 +304,19 @@ def _get_obs(self, image=None, state=None, factored=None): # pdb.set_trace() obs, info = data_generator.reset(seed=j) img = Image.fromarray(info['obs']) - img.save(os.path.join(temp_dir, 'reset_test.jpeg')) + img.save(os.path.join(temp_dir, f'run_{j}_reset.jpeg')) for i in range(MAX_STEPS): - rand_action = 6 - while (rand_action == 6): - rand_action = data_generator.env.action_space.sample() + observation, reward, terminated, truncated, info = data_generator.step(rand_action) - observation, reward, terminated, truncated, info = data_generator.step(rand_action) - - print('Current State :', observation) + # print('Current State :', observation) + print('Action: ', action_list[rand_action]) print('Info: ', info['state_dict']) print('Reward: ', reward) img = Image.fromarray(info['obs']) - - img.save(os.path.join(temp_dir, '{}_modified.jpeg'.format(i))) - - # img = Image.fromarray(info['original_obs']) - - # img.save(os.path.join(temp_dir, '{}_original.jpeg'.format(i))) - - + img.save(os.path.join(temp_dir, f'run_{j}_step_{i}_action_{rand_action}.jpeg')) diff --git a/data/temp_obs/0.jpeg b/data/temp_obs/0.jpeg deleted file mode 100644 index 73c0eafb7b0ff449fed4508baefb0191bcfb29a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37645 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 I;6Ho+AKV8t1poj5 diff --git a/data/temp_obs/0_modified.jpeg b/data/temp_obs/0_modified.jpeg deleted file mode 100644 index 4561814d96488df2baf121f5ca01b82f12facabb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 35196 zcmcG$cQ{;a+daHTiB1SY)I=9j1X02e(G$H!Li9vU)F6yV5F&aPo#ut%f`Tkuq7otk_io$~6u|ru2oVtxDG4bZ85y0xRmQ6V|LfOz13*cL1KFBR;aB^|;@CphE-xU!R zlX)O3C$FHWq^YH?qpPR?*woD2!t(hGD@P}17uVNr?(g3F`uTqd2n>&ijEatljf+o9 z&&d3em7SAYTvA$AUQt<9{iCs|`DaUOTYF#sz~IpE$mrPY-2B4g((=mc+RpCY{s9to zcyx?e7X)1AU$5T_`;T=|g6qP;!^6cRz^n^`;|gB5lz8}8Z(pF2Rwpoib?KVGTSDsl zVX5%%L~M67wrNZpdWmV-1!p;SFiXR(?Eh?GKL1xM`+H&kTGtpriVFd69xf#S1sc-= zxq<)n6~75jb$ynb&JjC9yx^Qn=R0{Ju5HEAxc{v8>=9tURy~;%!EEW-N4eWn13w2K zTTjRf3a704ymo3TrQ4hQ-)?$7vgqK8Q0i+(Y_{-qIy@5azBvi|VsKUk8}gx@aj&pE z^*A}R@>PA|h^sb-{nn1Yi(I#E!Qp^!NfY7-?PUs1Ux(X5l^%~@R`ToT(s zU`Q;o((X>FHh2QtUpIm$S%&c2dCF@f4|psO#YZdR5ZTA2YqtNWUuT3N(kIYB4<0SD zZ&Fk*=Bk{2z>n+$uA)3i=h_h3amz|3OY#V%8fmYlBltp8l^dBc@|R@aS)xO@Bn*GKh6QoX-wySJDa zcbYfx{|^_hl@8^a4%Jvk!>jL1A*P1<&bIuC1JQdoM%ip`6&ijuZ63Qjwox~Yv-DcN z3pi;z2ZmC}i37P)a0(w&xtwMCgdcG|Ca3K zgJIk-;=AoxXKB#T(`G;xKPWs;@#@7NS!C>=Nsl2DC&V688H6TqolmM{cVPLi&Vk|( zE$gLg=`swd|F(Pq8>ZZn{jQ?OxP?Et@VKd9uAulky* zu?|%mt8DaHywJV;>u7ijx?Q4shD;W`TPXoFCU3nEiv4Szs#PgOP1`S)&n{njLUCl* z2yQ|M+H#jVW_tCx5Z*#n)BH){`o0A0wifTN#2?>zsB&JjGjOP?uSvA1@23zCXbtOZ zSikIzCau+Ok=N`A^z$Z$o4fJ*F1X$*XCn7XuM{#YFc=jKJK7WRnHJfjbCwJgPu_hc z#hh;JL7Q$)Gr+a@s=qpEW-xx{RO0J*(>LWG>4Upud^R1%Pi`X!Y>2o1FQDOnf|K~o zFt&R^*?|K3!N6A;{hbdCDgB}dOXG7OC1mY6E=+rvZ$EbL&SqptG{;HHDZb7&x~{ri z>FY* zgYWE1e9xl>)a2wSl(Vb&yqx2-M3UBvgwE zHR_A~)k>dp%D!}aI@(~|vtwwK7aP27c?Mm{arTMakq;Hq3;^J5`4vg_cE zIzUMH&ppye3j~t-mJ$7%*Xx8C*j2Z9)}Y;QG^PwZ<87|n2mCxtK52JnS@Hayd*I&l zv6Ad#SUpF<$T{FqeMYg@l9NI#s3wi)b4y-bH@uC%N7?Haoyc{Zb0GiKI=U4F^#;Lh zYRDk#8prHkKu{nq{!LlHmP%?#=2u5y8-pn%N&&Ty%7xZypVa2g$G`d2#!*6-(rwGAXtz_(eE;V-hdrhB-4I}*H z=I~P_({ohUB=**|<^mNn_2%SUO}%pk9_f{pI^;RCCtLceQYB@CYzAkX1L3lU_0?2k z2_Nxx)1m?=o*94iNNNavDYCvQMf2vHHO0ZWogHjBJ~@oy<(Dpu$$F7BwRjPE?nNyMU=0Fz2`z*eeSg3WT|E=97V-9Y20%Q*Z48$)2yxXD51zJL`eK7^Yf-;CcK9JfCC1bNvv; zySljNgiQdSUcl(@O>x zPp#v7^bm``6K3+F;b9V@G`z1MOyHhmH0Dc3i zGH8z_Z&vWb<0!jLjm>ffeZo{{3OF)n>)8XIR{+#9A+mcrY0WFSgGQrFaO7Txt8#^& zP3AqNbKu8(s`_-#2}>qmDN7xp1aAu3Y=LN*#a9)NwZyqhOq>JVw_q;*6CpL8{>;mn zmvzZ(%u0ON>{2!&xNe*SnyUzr<3VB|dT!1j=S|z^5+^2aW^WhfL5?U8R`sPUYFZ@89RR=>ugRp2GC>A#uE%=Ku%cWN;jkaX4wMdSj`8Yb)7|^%Q<{lEp|< zYwlb8b+}_qO;yKb(aEHg;|0wv+rGPsDcz$>4C!rcM%t1y=YY(VH*YU^0vB9@Wt~j& zGcL-T>TIc7ezH$fqm?Pw#(f`AKjR+KZuQ+gZaGeB9Ptv(-alD&S|0%sLV#J`g6VtifEvM9eM4E8 zB~vGVWT@qe$2*us;^0}gC$vIRHT|b=fBuULVCN)P!$!DRW!dYMKNk? zjIOZ#)p`y@KU)%%T);xC1aCfyYNBK5;o>+Q61Ru^M_QWqO%V5E;)a$cU!n_Hq`dO_ zS3{IiH4M6t{TaPsRVs3F(n!fcAp~JiL<7a>Qrklexyf2RE%NBWf6V=7pX19eE;#xc z<)jdX#WCp*hQltpe%A9U*|5en7iQ(xu?X)_o?7%H z1iv$v-z_VQvb_i#8a#g`m;}I?E|*K0h}$Y#umSXv1}#0X)-r4%$gq2 zh2|eNCHB1dOz!8xa!iQ+QgvwNsl-_pH@XSAiF>=vLP9IqD}8!hiX?YECcZSe&J&Ki z+f?ra3&BfGcAfHQ{qtu;t{z$e2QPy5?|e!9Vm7GCI_EX#K;Si=F!hYcy} zY>@n1?|s9c&!p7Qc$;$$z-8IGX?pPWs?B`4I>(V&YkNbzr++<4emL1GoXl!zXp{aK z38PxM4)v_URMe`jOs0L$hG@ScG+Ixkv)&95ZUJJ94-3wV<)(EcMQS~^4FleFA8KWl1&U*;V^ z`wR5$s*S!W7k%L|QQ1g=BG^6yO9tdokPCaFR2b{3-FrLe7RxM4;a)E4Zuk@5`?Mlj zr(s;g^=B~0U#eHdeB&ZNPZ|_@jYE}3~qA0;4NVnSZL}-n+n1*7xz3= zX5tE53ZEK09{;abn|Ux@yy8=JYV){YfTm>)edlVB*fTnUxX;eV6qs&8XE=ZVeN#c5 ziKL#|Y0LV`^|yo0-+n!Q*m+_?uo&=K9nCeBHgHj4Zdc%;X1JRu_t`+Q-Bgn{FTf+s z`#myLo;7$NQVoB-;YRA^9dEkCl5F&4G^)2g$uswpUP%>gKhv5a{e?C)mYVwc36DT0 zq=x)!{<#Y#hqtNer?OJ1Av&1G3x2d)iD|r^{As*2j$DQqyUXX6OO?DHKsP7{PAIy| zv@5Hk*Ng-#C)^=HziZkJ&M*9Q{O|9Jd_Rh7xXHRngrG<{vmzOH3g~-&2kGXwvg;t9 zoBRq*P^+C+uEG8Rsad3#DJl)!0YOI` z+eHR;+-&Cb3FmX*V9=_j{M9&j_-S#tK+(-<`$Fs?1zz;qN%phzLbMoyGG>L7J|*Ah zIR~Emw0wk4sZP!MtD>m)kCVKjM5}EzI>!LE=K|Yu88cr+jT|Rf3d_uTa7ymLEjVI7 zhpQ-NfY`8l4^w8hewW!r_U({!V0iUNH%0f;aN41PKDrOS%V{&waBCFJfq=D~1BFry z`yfT8={T&HyQ}j9jnAp4OHQ!ERXF=p77vGzjkSm1Q?G#+M{jVH*JF-zKrVrw8Tuae zxG4oEk}Bh(0$ZpohpO!h{$7(xz2Pm8l+|mViS^)rEV~@~aiwL8h(zq|>C=Rj>2Ari z(8sdRQ?~-9g9@ryV$XpZ*n6+~uB`HbXZ;-G&kI=XqxD1DJ8OT0%pMSYm0In~F*Hc< z@VUDs&(Np3m9qlte$xYSbmM5%x~f5Q62|(YaCUvuEq7mCit2Ywop(r@XFYz0u(BSZ zr04QxDd`l5Tg$3Weg&4)!N*nRyaKhK5w!FQjmbwAX9=q#C!X9mi8LZ5mDXR%FT&## z@n7{b!Oombg@>4gpFRmbGf_ozqmv&4!3;Mii8hm4y>~N$N|QH(&jG_I6Mhwuk@1Xc z;^3yFc0fRD462yqtx^U1CX~#gMkfx~2b>^6gWn!c2tJe{&z(=_S&@g+kQu$hV18EI zEPe`f$}kg}eJbys3Z6a=xYIA0p?ir1a`WXKtWz;8UE_T``Fh$^{GK8@CsqnidU{Xp*32#|^~ zUI{Kd2U^Zz3Vs!z1JkcU*6KS}rKq{HnyDic{?%M8j_WxJkADm~TF6?ELHA-S#)%r9 z4)PJ7*PAZZimrP@OsZ+Y%cq}p-s@UBT8%lUybgvsG%YSjC|w$1P9aBE<>!5jv&-D$ z1WPRwfMKlZczG8zqzOQL0V1{6n=h+`ON?EQ_s)Z%W#50|D5Hl0^sh(ExjGfleTXYMXTr;3CXPFOmz#s=GgG2g>W~) zNHyH_u(>d^Pl45;?ec1}2DP$Lv`88VyGWS)w&H{*h5BLepi+VU6Lt+jN3-!x;Z_1Q z@mnZxi#kDc0;88EH|(x(eQ&wyFGrBd+@#f`Py0djC0e%5Ylj}xOr1T>ft&6?A+>-i zZwu9(Z%*3u1S#mnpx*^% zNil!3bfr1SaJ?mL8fxa@p>?o~rW*2Uc17}xpD~;6hQF3S2iEsb^Lns~6;4u4mTaz` zqBR%&A_IoMM?W!8wsz(y&3=$Qu7D~u`s&ey6dTn`MKpm$F}(n@&dm1xC~&}R2C%j!YB13R7eF@=#=8H7Dtu}wlT1Jo+V&VeuE zXTJ4AK947kE1XU}JV4!=n?r#WtRjKHeL|6YS9lL*F25w%2Smj!)ko`V_wARHt@7}w zCfeD2Nvf7{`-fMhCYcc%Vb^fm7tBFf#mV(}Kj)6EG0Np1hd)cO@5!GN-E*O! zdA6>9()R7gHr&pKisa9ZlbgFlBTwdB|?d%Wm-zEhK?r?GZY8MRPoMCTEK~9(FSGc8d@6>#o~_#HpY>nbwO7fhn`C;0 zlG{nYfoOVVFG=9F{K2Wam-fp4ApJay)|&~)j2dK9j|ThSsz;8^0-jMS(ejZ9^{h=o z1c9As_o3Q_u7bi*5N2eWCjX^yC;?*HCx!dt_T`1gi$5kP zG)Kkx+&IL%&5K3lu{I{#mD88PP%)<-EU!R`>L0oV zU~UNa(Hp&aMcSVDE>&gMoH*pvsADLmqa42UwBj;!uao7!k;{Z{i31V61nEh zhLK;I6I&}{j{>m-21a!bd;pCKj!Agg=ax#bPiNv3lkrj~EG^22wlqz8B)ekg+YkqCZa92K-b2zI{~ZVU!l58fWOgMA2A zU=ll6)$5;7cH{|vK~go(RkY9SlfW24{gK^9yT?z5Nt(tEDTu*962>g@^h5SdN&oEA zZ)*6wn3jIuo@5<5rX%?fWVirX@|INr0}s^<^UwR%+_;{7*`*^eLj44#ikU7I4&?5&ReT?a{rRd zQTq8(`(2a)ypX@DBD!x$*)7H(4x!b^Eea3 z9m{?s7}1Vp3Vc?Jg~zrPU{hliKD0c5Qf;ZIAM)l_m!=buc%FjuRbMH%&{7;fP&3LA z++ox3V;9M3r7WdfkTGxsG~m_(Vt-N3MjnKf0SFDaic!HdB5p>$Mmv&?@dM#gY&M)V zMgqH&w>hdS_-cSB$d>yAA}vboRo|jlV>(%RgRXJ^$VO5_#0}-GzK8?uO~zjtwkrBh z(hpF%g6dM2XTc7m^yK!^>p!jP8kBM>TQh7-l%_YZI8>VH6Ii<9h3W#N^vOrH$f;D$ zfw$mW#=LpdWuFALX$U3lbl$$zo=xv2`K}0c&+|DBiN_1O%-z}hzk-q)C^S5X_f^T) z!ln#JPv!`XxkP37!m&zsC9G-LEItMk=x^HxtO!OvrqHx>+5Q1_UL%` z*!J+k>*S8pxD^A#%w1iJlOJ!3vVV?{x^m@98J6Hsz5@+aZtz5Hsey&qZo50Vq*J)< zZMX!TM+hh{7f?g^e|;P4+HU*QG2z4pXKr#-*FFTbOGHibkz0j^>4DRl?wVML&51TK zfMq-F|6)6!lzL`2o{)UBM6ua(5{3#XnxEKDA-Uq2Q(L@ygD{Zl$j4&6K2@838Jdcd z`|I^J`HIp{DM8zd^+V8;mLephr&SH=&XbNMrNxAljkhZV#yVf?`)%tc>esb=E19!O z&=P0pQpkO*!I!*$!Uy_nhOqGjPz%=E`I!Ph01c9lafkudT)V7lTt&u&2obj-N;$fkJD zwaVBBI>A&2@*It+anz>xUgGGoWa$_;&cWQrY}r$=UfQfdeb2l;4X?+i>+o&L)?{^R zY%2&Wy*rFKl~>>7snA&(a%7%qmoj_R8@YeY`)XQX1%9;2rHT45`_T^_(3AA~;jCIf z_#yR=5nmeaRJsz3Gg%!>(7Ia(n5sLNw*}oMyW&A5xkIqM;`U239)*%4(b{Fb zCrthrl<;6#O3sl1yh4$kw4y5N-P?*IXB09=$Q0uKZvM_MiWxVSgOXKMGv!sn@A~Nk z%kr)$6(^^(8e4j(PGqJtDWY}QB~n#;1{s1ut3@Sc7YNhFGPnI z3baW81_DS76kYnIg;t&P!=oi$>!(8dhhD#to>Q;p5nnUY=;{nn;~rK zyu+z7)cSIIo9z^;Qm<6#=*r*KGp-?o?R0uzhQAq*pc;YlEWaf}7iN-J|LXRU;ypI7 zu>|${Z^t{;zai2E3z2dR&?a$~ofNV)40tZpXr{@!yi@DA>I?ILJLt=2Rf2n9^#vi` zMLFp;GQjN~Dl_etK~|W3ay7Yr{gmA~&@q;)(;Xn_m}!Ogvwo%DJY6y=?@&hwpiYTm z^^s=u5!V2bp%D1yZ6pVnxOAnLz&tQb-k@CmNSATtn0iK_`eNIa17`{U`uh?Md9K12 zUpP{_{IpzWydD;X&_f=RdqqN2#=4Y!1Yl0=Eq$?W-Oy@zMjU=?m<%<( zde*zYJe4=`RN1Lx=^~9BCAG1ZJ4CGquN*~T`?5q%Zc&2bzW6(Ytg?q)Sn;C^UcYWl zGOH*Z=b#9VnGbX@;2C26pWq2({j**7xMB{_cqmhFG)l1v$nb7Nx@e=3s<=!JumW}$ zWkzd>^;i?*C@F!heJ1~^vllU!3;4VqaD%LX&nT}` zgh?;Zur#+gwp6%xN9%KjWkiim1}oog6LMhLUso+*w!4a-itYa5SU#y?byD(>AMV{F z_L41kVCh}2!Ipjf5W}pkf3EkQ^5-gMucmU5Ej8}Ou=z6udwRl-_aWc@(c=+BJwhkG zK!*KlV&!W*>F9y(5^Nvj(g>9`KAzyq#f3ETfH4U0E0RP`8iyHPdrTyE*tWkfIiCs| z+Ulx-JX}$x0rZm?n_m!+z23;H%s}HLs>Af@#Uo?Jm3VLSiqe=ZGqXIDHq)8By=Jpa z@mS-TMMpx|DQLd^QNIOcy!yJ2B?xSS_klM1`%OLiseZI{CMt%i zIr|vMN>qMjhb*ZPFm*sN5hCQ_j00ML7BYr&=;et_Iv6?uKWv~+AOLr>;r{}mtGRKv zX~A<5It)kA7#5C(xk8E@a3iWGLoCo+pgJV6ivQUqkomOejk)c>>GIjuX2|e(Eg+52 zBW%5SZ{B44jAcxNWHBA4(J{3hq?G8Hjf3_5>>Kv%RghcoA6Y!aFZ0k`6MNb#IE$ax zekxl>pLH(B*ttM0&jA(_tJ0p@nr`Zk{xUv1QE$$HtWmplN1K{+pn?t!h7}@zqidI8>rG@RfDAcVxuTk-d~Suo^E@&qAa%d zSEVSL%lx0l=(1JlMVteH(5#`{NB1hI;y7JgCAxR>bOUdgfO;4SQ%N@C_2V;!!eJpf ztYLDq1D$NS9CCQ*jUVaiw8F5Bx)cr zgl@k($v6&90XTr8I0Mo3&Ho4T+`%G`j4MrAB%HwO)-buGDS8D>d3+A=rh%r} zLOf8$nfi(yUS0Izf#Vf9;anEuGxz>2Q$@;~#%l2PmupZTmH8F-kd88qJe|8lmufT@ z#vlHvmcjM0TT(R7bL?!VhGtVEvRCBg2tt3~eeD7<^i$zu@oe|hMUPvXymb7FRgv<< zmu)O@iw-1x3O37&P7-d|$?t^4_MA}6NiK&J0PdazovzXFCl3@Asc-#y^n}It;OJVt zwRM|*dZisx_atmv0?PY4O@R}g_oXFwb=N@ATa|ly((Y$X`P`JUK>%xGKv*g4pco6+2BKjlWEKsJ?(*w))~J83&H z$a6XeJpENumRGgE-pH&r7oaTr15ab#d_oH@?WRSf89{;@e}P!^z*+e?f*)O`XzjS> zku^UKHZuRxK7mAXG8*@7l5E-iXBW6^*2JNxx=*Kj8(Po7tk^fE@Rlpx?n~Sw=4y^? zX9UKZu*X2$Gfz-mdd83~r7!TRO6&srPK(S&h_ZObxOGH0e@4`aJU)Cb)-=L)*yAW?q4ayWQ zfwEzAc{%tBYlL~O*(GunJ=sK8n*zbx{fFx1XeV6v^^*&J_NXS^%-b1vz$3UGT@4hd zJaA*YcKyz6tRKL1Lo4ibS#L%LU0b(Ko^FpS7Hv4=VLo7$p$ROtlDndVNqVi1cu+LO z1FjMFroXy4E16hzz~t2~CT~Q0Tsv8pN;dN*wo;3c+i(q7;q|44te5}0lTir8^sNl_ z@Gh`#O^%HC0X+wdK(qht-y%2jU0s_*%TM{{&uC?;Il10PoKnafG7su-XC!F{vs=2X z!R_>I*tGQTTUgH z)0w2`f=xkxK#lAU$bK!vTvhW8rh&36+{y#BU(~%GymR2c`hx0ClH>Ns#dF|s27kkW zMDoto7FabTGTX|M-Jb3gUBAXMr#S#i+K1rNnCy-t`i-$zd=5-$_U|CTXw5#L6{>=< zGCzYkt^HHaT(JtWn9cX7n+sCzR07@Tm92wSDJoSni)c~4G|Rv@QEGRJLTa*B*H_=k z9}D@Tz}{(|3bq4wP6ItwlmfLr*%c+Rw)~%q>^fWOD_4UD69jMKfyi6dGZP5tXGPCx zvUhbYS7ooHdGqN{khm#?DSu}j_?Pq=I_rP3eCUEj1jesd({6G*3bgHEyx>}aqTy$EK$aA`89HRg~_vhgsa zYJPnvLj4?29M8VWVIdNFDKP}2A8xc*0l^-9J9Mnl_;rp&jL|65=_3zqFrbA~%hGtI z8<`jqb=_j=BJT2`KPVYq*$b@rGTrgTNZ$Ff_Ps(2re?tX7Y$kFfNnW_qG3Ee)Qn|S zQw<_bPX{)I%rE97FkSTS_Y=XY=iOPkXqr!k1$i&vYt?U}`=0&PMpyb^kyZ(Vv|Cb? zU}^zk(zRgl&^70^83Tuu*X}tG@@kV;zTe`+*oSh7hha!1P;K8t74US|XfcD!l^9k9 z3e)SgfJp=L#tAfip0bNGgJzaol7dnElpq(WytciDdkCxm(A~4m7kOvf-0i0K<^yb$ zAO{7FanEEge#EADz2qBX$?Z1I1kmMhX@3yL-2U4KK4gI(Gy9(d1zOoD1Ra+euQy+d za^lceReKTjml)h!{g!oewdd}@ON!Yoweit=trlU?3@=}rd%efz9f7xOZcjCYEL}v1 z)7b~7Ij33@5=$n?L-XF`p^sQvy_|+?71UGVnpY_OqQI_g9t5`*Ati6Y&h9*e*o>Aj zkO~stB6gJ`$WlK%(J>bjW#*w(7|F{a{q6rMs@of@<@`okOkr(uNg>w4m^CYPv|xHA z|4l%`-CLx>7`tx=+{42VTWg{IFskkJ8%?un?h#|9{LX|<){)`es6C#>_EBQ_m+8mJ zt!m(ZQ`4Vp_I$zANfx^R8o+}R*qD^tz5fV2>@#YMaiA6YM0)s+)wF*>>HtJ8&{1yn>ZeG5f)`I5C^DbW zhCSv6wch#bcK%C$T-FpqelXC(r%7^UcUSaB;Q)9B%FS{n*6n-AU**ZUV%E#>v#RorT`cVySto!NE#jOy}OE|AsjKa=ceUw5?2 z$jWOO2+3ZPC;=-4c7cYa*EVrY7VNv$T_h5!&lry8r*fO^1^3);%l+a)Nv$62=Up6~ z6RNC=Xnnt%#UlROj@9lsDRDFFAA3h-H||iy@EK{rmJN;eDuo!FU1|K%kry_d|F=yW z58AZh-$0voz)20F+YJW)Ho@TE9<1Vj2)AbAi1AJ$2s3Z65+L@>3QzbaVH69p0$^Jd z+Wk)z2k^#e0*JW03Eb<-cU~aaYxpcRqblS;$p>uADf$chLZ@V(gW8P@rC;T%y<`-u z8fxS8W{(+-?T)3K-4`%eN!wXQy7x~AvJ$@ z6Q9w^S%NTy@HyxwMvu*ISn6vMFw#iSF{faqZM)FcVwnj0ThsIsQkz*5AQ3tkP&4Ro zycvTbZ6g>(XRtJSXws{BiM{WeouZzFNXE|#cZMa1?m3Bwq!8c!cSvJS0vVk!h*NGC zS+P>jLd7@c<^6pcn#PC2R17{#woQ`gs_g9FO?ZvwGGdRc_?cOV9P>QrpXJE{%8qu( z3Nq5z_I4x#9l9q zQjpA9BU;mzJ}n6~$|9?F1q~Q_x663OTlQ;U_~93wSq!^VbBBz1i^0gOU4~q(v$&0I zuO69)?i#K3;I1AI+Z*2Pt7XIBYNmh8-?*AW){g1G7w;LTyKTdsH`LbznW%{u7S4iE z=fR;xe}BB_4!3+2J}2bNWtMw&?V$K~k7{bnAV>H?6~z!XZ@6Hh=)k@>|HMW)1&g%ZXH z1tJ~N3?Fi7rX21RlHtIA_t>k?9JQ?e4U$6${Kle=Fq$=#=IKT;03$^Z_GJl88pE=nqPOM(!2Ek85dAUpaj4)R^^@|kJK zS)@mD!EG+NtG=$e*aJfX>Z&#bfVhzj{LL0ErceRYis#;!#(}A5!P_G_z%N<0L1XulQixJw6BNI9FQj)aZjt)T!pHSo7mx?iM9}-F*YGo@S`0t?hV}sg@5F=WDmO{rGiVeKI(Ox$iI{U zSwND$JG#_D+gO31UH<60QO;t$BdTIOI+K z%bdpcQ%vLy$vE(HS6ut{2o7D4P$NZR{Umzj%yR{2GDA&2&%jEhzLpJj554LyXCk?k ziu;*)LYrjuE3+d_1JNQ=8V8-$F~#~+?m^xLI@!D)bhT%zPIiL*vDxkvVoc_k=6AN+ zGH$-ZAX$Ad;yC0Dn23!ZqF+wbnN$pY)9~(7<)*5A0U)D$t(fRa_v7^cRcOFy2XV@pOCg(n$Ok{?Pj+OCNsrO@hJUH<;Md_9{ucwzxAjxQ9e&S z6f`S^Mh7&VPN!FglAkk9+{ft@FW#p(eS0dg=KIL@|jsR3?T5xaF-w9_N}QuIC^b@0yP4=+FhA)LEoTD?F+wU0Kx6-CfTREBeD%lN zPdh*k@N%nbN+Hy^9@$xn`cT& zYhGTPM4^&mncg|IZ3XUsveb?5{FOdp0J9vI8#j}Jxm{%%{kG%{p1lBFzn0UIfdlEo z@3>&p^mIqh_1JeP%VGF(gkUlAatac+D0fh(ARkphf?ul2SJ10w)^j0f%tlgpyR;f_ zQ7+x;%Tq}WQ4z+>*RsEA%3}l!x_mi6Yd@^@TJ6uxp>?T&c_T?^nXG^3&2OgeEU)xn zmrf;U;aT$YOaiR=)10Zqp#6(UBs|A$d!7b{neM@l`YQb<7~Kkcl4Y5?`@#8>ou9j{ z@SlH@*kcuelsKc^#dA9XJr5|_v#M`1ISxRk>xJ$s4+aYRwUMfa`GtX;a{viWPW{r< z!KAFDTiMD04CPtl>`&*K3fY z$5Qj9|DB3Z%ZqoI@XS`WOQ#HK)tkjhBA;K8r?EqfujUu)-HcmWOt18E37RLSc(vxX z@{${;c$A|!zHs4@t!sOgY+l*WU+>@f6!GF_-~ZLI9>rzW&)v1&t35*&PU18g>bhZ1Fb#j3#>1 zKaLlFWb8g|EK5#o!>ukq?1?m*nsw;QZXiwHXWvOK zP)kBNS&%sG^6$03i-v(t$>N3-mBmowCIZYMHV?6%LO+0EsDI@l_+Ef{Jy6Y1E#5tz z7|-EZ+c{uctM!W8r@5a@U5MAl2YR}T3J9xT2!-#M!tv{K3YeI-pM+&2!R)L`Aa8To z=NRHXb5q~HwSR9`wdMvXsp;NU*|G zk5Aa@0dm8aR>S}=W;ntrUH~_>wY62UWh_0-n}4d|gT@@-)h(<9EA{}H8eIFjjIyRf zpT58nkDMzqz+WE86avqTXzN>e9`#^2@MYKft{m8OZn0oge;`ntLt)6H zrg7al_|om(C%bUphvdz2hh}2SV2C4Hj+e+h{KaFi;$cbJ!xR!>T@t)ZbB!L*5lgSc zPDg0oD2N}LP2;0;)@5Q+z0Z54-X5K3jg;x!!RcWF zm=}h=#@P+K^ci&i5Vx?&=z2+|^4Wbk6?X)g{pOg@8?08yE&iaOQ;Ss$_blXCu4I{$19xni!GFjoI__Ba(aL%ObfsW9dzy zrfS;LbHTQ@v_eIPqwB)&!OIjH%dQIe+_Vh}H@{O-8;ZakUW45@AZuR#MdwRnTtRS+ zeZ><47>~Uf`&xJ7m_{?WI0D+ZhJ`lbIZMD8eZ8;O*v2=5z8-mZqNUgMent*r;EB|J z{mJIgph?$|b_c&a&)RRdYt%%7BWSzbEB)a6h7@z0PX595S_w`A{jr;(E~17Ro*vqX zkH-cI>T#s6&u|_d8!>>eBErx{*S>SL7)#*eukB2xo>cIWW-+_d(azM^Fl%I z$MFJ+dSu^&pH`@HIN538LWpWWoeRqGl(WowndNSn_POyveQ>5PI?Gp zU&qM8w~>X=@Lz5=yLU%bh`&J4H@ zThaDjs8Xhx9B%^{M{oj32qrqan|vFqlu^tX?J&t#ewj2#(C_qk#{&s#k;BX|mLm8U z2KnQEX~kVVN^|VNanta`aFw15=7t8`8sutM4IQu6`Omv>cpTTc$bFcyGX6C8+J#0-JN#Zb@M75Ag%_FczCCAo(I1Gyn{Y+$-FQ!{#>?-70)ow2c>C??y6wV=3aD#I7; z9_!rU!8iCa;nb4($m5DafCsT}u%^HCDFsG4JNjE`nYs)rEr>U9pwbc~4Ex{$oi}vU z*&kmmT|fM4ycoG#KLzS!T3Kvh(mO~y(uWZ7qErokd_aHRU?mbibR+6t%w8i8Jl~{2 z;XXY|!U_ag*(fGiJ z8z@(Pm!$Ct3WfRlS367qK=j{9JFbC?u3dXKOEUY1Uq*;^YN>QOBo1;=9?>IzvjB=d$>la(-GSkP83 zAgu8ofiqhu8$_IKuI@v-nZIO*O0x!04yX~~U3@7o^Vq?lEthvvD&<#V1+ECBzD`w& z!f_o$!p=PSDBr7m)K}vGKW(6+zQ=`m`5?&Le}%`P zFHNfUA3YmX0(i9Jn4T(PlYUAc`a~XRbYe&7zAYGxI64P>B~YNL1C{4DAq&vkQkRr1 zZl+xcES4c*RO!4$bF#s-HvrjMRg+jVNdK>M@X`E=WAkU%mn)oi$Ao4;ATJgpWtP>c zuCO-n`%q*&_yi;0fDj-ELck;I-;{r3Hu7KHUTYyGKVJG9vty8n_6%BmGh4rBYkD0h zX6n6tk3D(DouvVcL}&}u=Knh^Khq;IN><~)oWXWx>c#TouL*1HJiJqYn5SwEN)U24 z(cZMVoa-M$^EuHKroX~&Bqq@xMuo65|2iNz4n6>fZ=&ZWH!NS9{aoA>qZ|n_5zWp$ zhGmVq$tV1?h@@agWgk}*zcAffe1%{4YN>L~liC%!Fy}2k?PtjT?$T>b-B=FaS%Jr0 zrypN5tfSYRpl6PT?>OP6X>0~7ic3$P<;TCz+hYM|Jwo=j42d{)n;B$G{OGz#7r?Mu zRuPh=z}1U>2v)`?tTbBn9ynTSEK$3#AAYY`FkD<5-f@R9-1C<(W(HLCr`X*@3S=b7 zN$XEe-0EXAOULR{^Q(}^JV2U`6_rB4m{w7iO#aIm?OCy{}sg6 zzXHP$_Z`{J`{-K`({g8AUzkz4^YK#l;79Sd_B>QPm`Qc%Nm!FJ^IU?novr2VX!1(Z zU@?KD_iEriP!0T@;lt#BQwR*6NaU~cJ`4M<+52|p9YUVQ{i(n$ot5@$MWJ?bb_QoX z;$i*$_3k0IW&YD(=Z+!6$r_S7$FB~uWL~41HwrmgBi}JpC``PR40LB{?DM`By-yfV z^5E7FxqnUdh$&3*ToI+t%i(SJpnQ~qQ=m7&uF|Ut>W1T-7Zmo5H^tD2e+8%}1O-gl zLjSUawY_fcpFr6PI)T{Qr+@h%_`lVUou~>K@K%OwhYTNqPiz5( zEn!pJ5BxVhV(5&~Gia7VqfBXVXrPPwFWp!gJ2U{ASD;|Y9ZY@Wu#3QW%@bcQu$3^{ zqhi;XjrVp;1o%`9RqBZ8%OAemfsE~}!NFkiHzBsedeLC)k21D@1G!8yxUwmP;!e?6FF0L65ogef~?H zqeU-j507NyUx2DWdAi*Vb>$~5@8hHv{bgY*o;&M`$k%*THD?QrnZ-%TTVeexqQ_dH zYwD}JZ_R0SGr|>7nTGRcVPIM&cWOMJ$}ixfH0$&w=6NjSOOausevz$G+H?=pebra+ zrNQaZL-W_1il!!C{aFVSR?@Hj2S*oDDHv7xU^wOA)qR&DWL6?!8?B#09I0K1IEi?T zOuciBC3blccUa=~mc~)}&^_t$x%rxW$p=uxyMdGB4ltr6P7^GYbbtx|rO=0=!QdaX zKp{Ryo-*S)Q{3!~CaT3j)p5mxIZ6%$VI3?8TbPD}PbJ~{R(>LQB4hW-?{FG3#=kc$ zgl|-OZFgd%;d<3EU*qt4}Knx`nxfe@5Tvq*tBE` zOa|eZ{Ydy(_wwA7$hdVI*TZ9qEf!RyREv9RIU#xHu^UQ&NKBofE#S9v> zH&qb}bgIzE=ScYK?`gY z;lsCql4DTkIir~I81noJ^c!Bby9*?Ns=aD$g`S!2hiFjZ6aIIJkN&sBSA?)yY=&38 z&MNs3^?ANsIy_|3E3u`bFAWR4OIYB&^#^zhzUN4jpD2W-frf3=UK~Zb<#>-v>yr1? z-Hm+F1l#78(_KwW_~1EqI{YlRpt-X`!!1H`zK7hKLP`uG+eBe4-pF~EXAP93KOiwm zkK@Auj=n8W=}F8Yt)DWS%juP3uD5oiSr|*-i z(a9luUy;}}4ENfxjr-R`j*^+XQ=dY%D@+Xy?g<#EY`0^%Fj5FX({|V*x0iBjgXl28z5GkqFQ(4R3GlNI4{(N)~bbbz#xE@Y{HG0D++*38i zf5Y>p)57u}GC&^Nsm>9DtjH>0`ybOW`2XDfSfxxsq? zs`;U)|Mq35ATj*@pQml4XGtW?_E5K5t9DsgCkQc50;p2KD`)P(B=*z${0n;++Y+Xlx_WdaT^6{0osH(149|B0ct#$I1UR6~!|9TL(~v)}U?z^(hfpXYf$%+CNn zsMmF#YaQ!2{%Z%pL-F=_rX2{H4gCl3r90^J?j>&?;OGp1^5{9Qg^5k6*M|IhG~pSn zvjtoA3nB>>*}%6KvsqKJ$ZKS+JZeOz2rM8hn0=>tb_zLko_*At_{Mq6$06~48Az>pzaMb`7mhIU@R|281Gr$C z>nzHg+;(y(7>fz1m@a;cw+VN}curGAvh~&SqR+LH2r9=I-XlDaQ_IW*w15mi3y22o zkPJdSG>c9N>0#QXO7P@C^@Y^JLUoB~hQb`aLIyVIDTq3e(!c>-2u&27tGJ=lyO&WzW*iOKR-$ zXOmIXGtR=BdKT@PFKz&e0>Zs4ZRx_I%leq)*KrE(>Kfn$`Akk;+O8hcJ$eUd?=Gxa zX0TM_b7>lw_#g3VI0Z;jZ8OteZ(;ffH#BMq^f+Ojrz>vTyzBk?kS+eA_B+y1QD82v z{wFlzL6kD->z&q8lxt&~;&^|WEpJ4mblRn9ekFo)(gse{PdGvYY)^~>gU?2WnZq$I zTib7VS9>Rcs{ztA$~CUhOLAfR8)YrQrOTH@qDFE|O3QD=oU0~-@CEe$asY*Zu;p%N z9!&9_&zUP25$*)loCYOS`OkTrKS%@s6C2&+zSF)FFeBv7R*bfl(m$+Yk7qkVY<<^q zeigIMT3F^xwI}=PGCQ-F`au$yrg_~6Y6msdyu}A(@UMeaT#P83RzQ~#`(CaD7Ls;r zxQ=h%DPtIq@4Qbj(Q*xt_pdNb*+R{T=$M-09}7)-xakEh@2wVgPje6BHeJ!9Iwr~{%z z@y?!-TUDlA*10}YQTcY z#%2i;A*n+b=BW#rF+lkP%Mr0E4LxsFUcLql)x-x^w)df;QpWhwpsw}%5u?ZW8+I|# zh{w)&NEAgXa@J^su=c{|de=UF!qxFyBJs{i&5e5-EvN9RxC)a`a}4@dvFygMNI%tO zbZzZV9Sa_xHO|+6^B?R{#86w#kmRxv08kw8JQ!E;O&&haj#`*@Gt!toVKKo3r|>?! zoeYC5*xK3?m+xfd0jAaAA_Wj6an%}Wc~{ApkQ|fOx$?rIpKAyE7n30Kg|T|; zF6X`hvDDNFc2jCLU!N3E2PtB2=%wE48qB%-mwu|vcIZ#^mqARCAtQut}u zS=blwXGqko>w)Y33f1O^NokYi2`Q8tI0SeB%<78}bY5QhW6XjjM!vFQQfWZ1M`k=2 z&j!31YQ>04LvgZdGHX^{>|a~^1g#Z4LU8YW<#zpSqBCB-K(DHi^swrJE&6l~8F%^c zmMN4fYKsAiR-0k+Ifu7Zoy=(R^y<;3`_5mc`>l^_s%EfLF>Hopu-6P24l>I~@(%A~ zR{T~3XaAATt4nV*l#ZEswrqq$UA7L2sW3N`@NyHzpZkG1}xZk~@>Ps1>oC z0gB`LX=nywag2*JggW$OkLt)eamC(@vGy+j_?3oXz+Yi1Ew|Ku8U<@eflTGc4){mW zT1=4gA-}TV*(`A?g|Wk^SD!wwml3Vs67>ak1G6+ov$61xYRZ1ZhRWJnvX0u1FwnM3 z>53$L!Ty?fB~5netO|_`EN+&z?a9zxyS*?3b)PrHA{spWm4m7AioP4suKAo1WbnFh zI;1okn})>-n@RQzLRX3HzK4%)SVTXBV#i#09hDIYrz)7Z3OZAZmH8u}ct<<2Kw&Vz z@Sq4W<_$PD18#Z}mR5Ey_F=<~8*&X5zS56;)s@^`>Q zdJ!=T{=tR2hDYr7!#(UOjh3CxaCrq77M3p<7pF|aBHTwCHt?p?TPvyJ9ws(YhsoJV*^ zY`^>sTMnJXi%h6-SGx*kTdlWDzDz!f%FWg~gWIa&0P94^5tG1cZv- zBsrP}j^DofK6D&C2v*RtIv@)>5Wt5b)F9&3d8%rNHo9b&DB=}?1RBQM)6zHE%j`{e zUH!nT-))AH9)xz|H@b^NOTOtzVb>G4)@96!Q5%z~d;lCunIiN!1a1ET2js9{yN<>? zy%-q=oMg%7So%j1<#0S(L{^hU#v35F)efx+wf|!cQWfdu8^&pln|m};78#kS(}g{7 zDWBI%&a7a>Km39tGcsX*v`?$bgHo1q;!d*RF<{1S3obn+1c)3^L0)GEjhQ~SuTNUz zj*^S=-~$gY>J1;5C&0yUwNkHUW(ac#m^L%&8dzIj}ZFHqSSpJrw1bp7c&$zhf0cA zld<1ouLXaor1n>{(SP|@rLUOZ1s$ws?mN;0J zq>M1Jl~BW#hUAYQTMpsbf-tt7sB3(LAK*X8M?@4Z>3@$LL3;S!8ESqE5!gD9fq&>x z^qz`3Uy*{}HPs-TgF}e=n_w$B!3{|SC=d3s>vM{h za9mt<=6)?T5SGQHLW57!vfyDz-G!?HrqwS1NCyq3%X!0@E84$YQ9-xS{%a~dpZ0H( zPVb=IcD5r1$L@tOS-_!sgXT~*4CjfX63us%K{}{}`JfGu)aahAsj#-JQ01hM8(;Ag zqJ&wIJ3~gK{c9LTLdJ^x;1q;NLqMHM$*TVYL#4E8(L9_CqJH*0yC+e<8W7@gwp58g z>Wv2;+%*#(B&CYCC4X~J8~Aby{{8xYWCdde5H|KqO@}jrg_9qbi2L7qJpR*q1mf)$ zz%NG!M#x$J+X%T&p@jFZh`E`;+y}BW&F3q0pd>`S``MUPi)9?8+({deBA5B>V+hbTHFiS>8hKSzo6{T*aardnl)fs}PyY zcrjgw->U)km`^HJsztyWf4 zj0^W=g#C#Vccg))IbQ3NfBR?fWd7dE;f&Hxq1~BS9nTqO;v=EJ7n+KfcTB~@N=V6J z22{N5Y_jb3koT!*$WRh?)|IlDIVEZq-Sv2)2IM{gGNF~(_m<3aKMK+QD+;pEq~OuF z_^t1YDj79gBz|MUFaE2#8ID#rkAM$Jz$C&A8c~nr-00u|=K{K-m4+%>;x#TY&<>+$ zOYfwkZ`x?F$Nxoc;_-wNmoJzBTaoG;V8J3!y=Lg^b(sGt)W%_1Ac92bt5vAjODJ%?brrD654<+&i8y+@*h zUgUdoNL)Bm|LcTp1x7*X6C<}I49NCLXVKYBG(zJZ9wSjZI=d+eJfp=W2>%cXqL;*1 zpy5N#9UQ^v%nw*j$Sbey`UbKPnM)wB3G2*3<3}9dUoFF|wu_?Yp^MWG}ESM{xZKE!*r zU@};4nnn)hW$N=D4^$5lx4zqaATp5y!Hi|P^#xB<=^dbR<+Pd76g}r^V{+5Dv{tZ- zTG$8HNK$d^xYC3^y1G(5oge934yewJeU*n0JxETL|GRC2FKQ|w5g-Cy4@aSlOgJQ{ zL>xQlv?DT8}K4MUc=iC&!Xu<&iCHC^y$P_XCRQ%3h+vDeyJ<_e` z>Vh=_hmgr1T&4?4dY8~f{>1Nq%LL2+6(}r+9P#r#)vtKudD1d)n3jz2!b?38XGf6_ z#-9R}OyV2|ce8+-=(uQ?-7!?J*tnww1#_UJvlm(4q4tRT>*458p>>@61{WQloa0ES zoLx|!BuuNum%%9R+);vlrEq-ow(=_R7JMmBrzo68@85hkt>2RIW*AXQ$|InZ(*OzU zUsm%H*mu@`Rylk0NH*m?=p==MN^ift_?F$XW|!oPB*kpA0pf@M-hqnA5*1fW^B;2s zj=M`2)5lsZU;CQ9PSA9Z+TUha2RO3-#D=LuDkC&>mHMRi$IvyiTa4hJp=)#|r)hsQ zW9jp>Y8}Rwlo%S&Fy8SBtZ~#b4OnqJDjHv|s-%9_e1m!5pc(K6aGAmKh2%tm!)C)qF^_wpxC-ks>Ta3Z@y;6N|mWX>PP?qsuaj9k+cr^Y>Lh zj2GV#dAI|VzR=mNcb$rH9kt38LdlD&DdC{C0~b`7h2?AH)ADB+)QO)&eXBx$>?9FI z^z2i8-lHNMLufS(FbuiV9ej`LP&az?rIDm7s2I#yrlg9l>$+kCmr_!gJ^!uYg-YML zqPF>t&{>D?YdZPiG-Z66JkC!M3`f%=ivx>@vOZ?N4S@hmW?HS6*T<*HFh-T+0*uO^ zUVAx9ZA9q_Bd6|aw!>;*3kd$GhF1>k%fx5a6?~a|bE+>hjiJo6kw9V$)LQ{{D%|^? zt1Zr_C*2}~bobZ&({B~uK%Oa6WqjPE+XA9dSpeNgetI|-9v_Znl_1Kh2Sr(pOn61= zkEVg~5~)1?>e)w3e9q0cLB~^{1-3kxPFbx@NtN!!7=eHxU!ZG-+95sJsQ!am`VH;Z zx;p3TYjy@Mtp<3$8$w+;1d#u`#z6ARTM>!I;Ma&7yfpU;J^LBH`Lj{5qFd4>j6qo^{{iw~Z%~CC>USH3XQd2khR=06* ziqpB5_>VmN#b|{jEiDB(hP`rjG{R?O6!hy`^%u9v@m^W!w;xzv_qdBjGSMIk4u27u z-a|yDffFK=N`}$_Uu#ByuQ+y#cfSBFG*=C=KuiC7ko14<6nv;#6MRjw=INbg)`p}L zE8q2F&XGd5{GZc7_BSqo3!6wmbL!%QL4;P2M&t(`>`qhyMeNAmI9H*7 zwBQ6t3!*2ag^;uK>(5uI#cdL6rDQ!=)*w(~wPNcrD6w0`sITKgKb`l<+2@H^2jXFW zEawjr-iyy?exIkp%$tSdim1#-YwGv%MraU@`_#5@=^7J9e%{kazAE77eLLajErY1u zKHp|%DbT#2Y1JyIH4nQx+F>02)z3kq$x&o*H+!ewe(WN9so}#q5R``GF14w;7jn^B z^)}Inn=RFeiYWymP>FZBB&b_rg0zkTP?~O_2OA(8SB2yQj>V@ErB@$TTsX&uqOF|= zY!0>vjvo<^5;^{g4?o5pK~9L473!dc&${>6qz%w&5t?iX>@icSG{0~mCmB*1-`g9( z5g3Eu9qUivZOh_9HDk*QXGCo@NpLAn$T`HpGPK>L16FV0Xuk+JxD~s|KpcnI#q-Wb zxR3M-^I2xB#B3UmbLYQn{G-_<(9?JUoBQT({}AfiIo%I+`Uu)YfJ4xuBtCKbTtE+h%-%< zlPq&(&!Rg^9MtG5DFC@Q|gosi~l;zL^MV3B! z1;+|dn$C6XhV~xReNBrnMRM-MpV6ndtK_3xj)nB*N>fb2$^(KlRV^*DI@YU|-D_21 zgLJ4ylyb@PtN4`}YRVN}tGf?}^*h&6CXbF5u)ruX3A1`&N;IGlU`pPo?7Wp;=v!2! z{_)$nnM53KmRCo%z+*;P_0jKXp4#rh{Gf}@)UC@a*ap- z#DYcvVx+pCcS>bP92vii7~g$Z1%N$Ji>L%9(ZCa43_RhkbZZ4DiNrL7Rn|uXV8XS- z_DL;@d`?Zvb7R*IN!%XS`I{%j81kfG98Y0t(Ua)oDGcC0YX_8;YpUR41t@n%o!HVF z=&SFRTnJt-D+8`{LN(xYEpF=PDZrHY-RTN*FNMVWlMmUg7r02rA^qTX`{=#P)D8=t z!EQ$3)em@2U1sWq>QvJ-R44;muB6u(dwg4mnOMQ-w__a`PxkOoB3E$!iC$(uHEXcu z-3^&r92QUs3?btW+b2Eh-ku-!VbdONb8KgTvAwJ+1e+q5a*xu_(sBUiHlIffjp!&| z26A&N%Sj+^3IF|7Od&OX?hH%;A(W@Ms6yW>F#zm>-sa%JOn$Yt|f7G3Gfd>Ru=PVTz|F@L?)*k4rNgc$v~dbOZ*M(mUI5U(cd&} z3Q7FBg`eGPaDa+{BRnz;UMt*a`W6cGFcY5waJeD0pB#To!(7SW_pUJ&vi zQDGa4YT+AEu)`iDJ!)E>2;5-uVN-g5I6Lz7M+^6Ytp(_?L2Bs3>$L|z%7@snAnI1A zohry#$XL6O4~OSZL_;xUAgW_7_2s=6E^x_#br+y+!3h;O=}RyG2C~np3ydEb4jH!h zopSmIZd~?iFlx6}B*kf98P(WUMXh?cbf#OLkI;zu3P9$}71cm)f17pTs3lAvT$i5v zeeR&P|A)t^{)@+%!-4q4wF>6RZv`H%dE%dYWr~d30F|)Bk2gZQ1;7mnJzuBxCm)qQ zosF(!3mq8r7|>65weD3I;T&(PN^VgoWd0j=(HoHmGcc#6EJu=CU%xz}nIKWHmkQ9z z02cRt>g!q8W%=lM69&q|)cERb0k-Bkdpw0|mFp`E*3KNB^7O?FIaybufDYP)sibDD zY9#J-8AE3hum^V!i9uesKN|@!`Ygx9n547H-f7}HzU^7QEZa11_UTYHl7z+WXN?#w zcT=rlf5Swg4ajBjCPX`!@VT)D!7020W){j^LvfNR_@L^wd1@{>r*ifmV%T_^Bw8L&7odhT)vP7v`$6609O}@q7o& zKuu|bmb*MD$Gw>TOBu2l*qt)kY52`B7kl28_P_}7y@84ZlX?EU?~^V!@@5U z42fY09g9B)l+my6Wj*#ThJmfXK$wp7=AFR>PxglKakEveu@rrt4?VBvMWVN?+~ykz zDYZ2w)O))Pxi&_Nh!bgUCNvC?Va)#xGc7BaTO(Bv)J9iGhk+tfIXb$sj`d$gSw3C4 ztOD5cnPvbT_z|szK;~%xO$MuA01xj@JOt#skehKOq{)X$Qm;m`JlJMR5$kO+%jGl7 zKWV`hfov)v_BRK+;rGaI`ryqG1)c z_IQ^@jA2G%<@@%nZgl7$18Ux(k9-7g%&v#;@D6wD!nB6$p*?%1d5K!#+r5c$JGj;TJ5w$W)(cldn68MW zU=Vv}K^gx#^MJM&TnW~@95+ID@oa#_Oa+`XCX9swjJv78(+==ez6zUsKXGHQ~( zBgif62Y)vAE(hd@fdvnogpVE={0gCGf*Gl5IY-%D<_d563E>+QrvCsY&+#Bw05-v) zizV-kk`7yf=wsi3xXzeelFOXREj};#1kBMbpUMKJ_Ve@v zXOBRW$mFpRn!=GqC8+WJPud?^49EN%cIZ9iK03m6w2LOMM2lhGgBd0G)C(~HP0K|k)#KkyJ5Sks5NW%Zy{!wnI%D8c(shJNbTf3v^%2g zVTP99+^Y85?2!l8{^Tsd<;h@4(T~2|yD~#E{C*q*osWUK-yd~oFvm$^5}bW4x9|HL z0gM9e^r#|^JDW$9p{0QQ$1a~12>NP%>@vID2B4D=%fyEvkLt2sUrJ2^g6VoTe%pP) z^OwqnUna0toZ{r1o{JJs0Sru5$1gyf8CG}h(|C6yuCzw_lD96j_RG?W^A&hy3W3zU z-y?t2=6-m^X=p!bWqq%KZqJk%8m^D-yszj^2@gl+KqiJHTqt)BFKMGHl8HR$Z|OS% zT6LqYk_)d#;z2+L)MP#v#9$Hb7+U58ZkX(0v{P5^-=&HWtwhY(0lSD&z|b5{(S>UV zJ$&LQ=HXPnGcZ;Qd`A5=n`*DbF}gg-TaA(7)jm0&vH?%|(>vhw(=Ld+X)#X~Vqkd4 zxwr*LEFh%IildPQ##rJjGHU66!|wa9U>#XJx)1lH+Nbl*Q%%AI*O|frgHA$57no70 zv_2-sF5@tKxsffhd4!iyk=|ynE1ZdxB;LJLR{`&U=@OFoKQ=b0@^v++yFUJNn_;4? zr&xC!+Kv&*7}@$xfRgp%U4CN$-1LfIFU_gTL5NAZ`mupSFe%#t4G}ENo(TVauM|@9 zD2d41la2`P`Ta#6A)8E|^~HtrVfjSuwwGP7kX?9Il02*rTpwtR*mJk=?!(vwzJ<); z1*j5IWu3I6cD$aeXKxHHr%>kj&>t?)C_5Ex=n>bo+xRWi1JdbypIm-{bF{KOh2YG{i0^(EeB% zYjL}-{-rpYpr~LkvCDS^FaB?s;0i}BXUPKg?LrRA2^x+4$no6nUxmcKDz?YrsolKxEJn7fQCk4-9MY|&H5aw7@UCmaz$T7q`{6qI8!;St zi!$6L(W1bcSkXgBlJPXZwi{k$48|IdaMSA7_`RF~?NzN0_XA2q&1>U;mQB`+juhoR& z2M?)FNmkuo57`7z7rckJwz0;2Zo(LSaAg*7^e%=C1rIdF3Ta<$@U9R2aU^)eVwt&I zCT*0(Xlp%lG}Y?v~PConUaAxpS=+0(`J>=FLCKw9iy$%u;_B;H5!6 z;YLOm>#7z<~0r&kbO0N$) zvW=t3G(1jj-cGnL=NOkx5dz_i(Re6cz+3?RKvfNvG78ySou%Pf)F<|MJ3_>_HU%=5 zO|tdBb+gmYlyI<$WaB&gauv@n)dkz`XBS?wO4mqreeIpQb?#CNfapvRE}8lC`ZE(v zT(xr>ft3|BAE&Vr(Z>407jVjg(2ClFLHaY+8cl)GO1p0sgoqvXyD&A~ z>da^#*nA66u4kWMF36hK;Ly12{iK~If_qP_Q-Acxn=SuW)uD%)+2uVjV17AV0V`~m z^L|<*5_rghSyj~n;T<7i^LCV9svkasAK^6^xxuh1RdN(+PJ#Hi_BVu!s``rF;^bC+KF%Qr!b)}K?AYt zj5Y6+!C~MUI>UA*Bf=S{6YHr`y%I2-g#^LIf2^j>%I*kg&p4cPb?l(4^8<&`0QxW* zmwpQ!MhjTz|Hg9Bi>}wHj@01dbgjWZ<5^}y4dCq6>9Q9(NTsIP8gPC1tJu$4iC_@s z%2K*CE3YEliyw@N_4k$_KzsiVoW#(x@IQRcb-2jrK2$I(CuQy+b*Dol=ZhHm%R9?} zG8Y-9vPo?^0jZ1w+3FOaW5PR7!1?w~4tDrvA9Td6zah#X9uGks9q=wicu!A_$%OXx zW<7+M8!IZT>-T?riD>$)i*Kwy*oDO^#sMxFSD0E<4E+zz8Csp&Yp8<4PmN>EUE5d_ zG}#RQ!5ur;Ny52U@Y|c)3B9>&HJ@k7u1V;Vh@8HhVrV!S3+B-P0I80=IOe=Z8)EnG#Flb+VnF%6f6@MJOHA#&SX&I$x<=@>s>&4$+?E`OE)(&6f3Fp_JMGDIYy7=UuvqdgWo z6T#jpD=n&S_!a`7C*Co`h=k-s>jZ%1{wBb=+FZA>lO45}?BSNcic3R;pAH0tQw%03 zBu+4xY&GDvKIQ}SobrLySL%B6Y8%~RdHUxEDiF1}psuyhUB!@vHbdwc>W=$n0i2ZixK8k!HdTz`{(Jkl z`yn8zb@Ir*A88!;u}5%|SAqrMw0dUe`ySH#ai*Vk%#Gw(6;D8Y1Qef=TQmL^4F|80 z0R({{1MeV4G(nh8vJz*r7QT_SLxW1s5h@AM9V{k=%mDB&?AfDDFll~cx=%;oQK37s z$U|Rr7mv#bh9iS-@@orVSrzz#EOyfwiErG%?!gV0ROsioniBiaXl!gf-8*`qh$E@y zOpvV^DhA$W5uMxB9nXzdE+pWA9V7%&6&g{^7HMQZj6^-_>OF}2a}=?gR!w5BO#~n+ zVf7Cm!C41xU)&a@~vHZ*j8Gp7-(8&R$!aR}fWgBOh2;^qoDOm^C^Ame+6Ty7R4?uf zUA2OA`PO^)%B4?zj}K#?%+N6;cm~5vf5+SY`{&9=!A#Gm!X+5|a=~H@sL61uftrj- zfg60_P0#-s)RC_^P!ip@HTMk0gotB;hh}sQ#5d>*=QDky4`CW%jIho0B(5u%^I?Z+ z_+T*pfaQGZr{an`;N$|n4t>-f+ShTlDyaLuh95P6Cxn7}r0S@9|6nJZab{*aiSY9F z?Kla-{)-(=4b+ytbSW&`c$GR-NQ)^JhyVV~EY7s6<@afXASYN@XI(+>q~v!LpjiBQp!%ZfQ73hOrrgb=&sf*AE4?TVpCu7E8H|6G z=}Wx^woPsw&o|k;i$5B6%&(c!aQ2l0scdoUm?u*vckV>F2YGTu9Dnziq%$5$tDPCtM~ z$(WE&pOAFHXlQb$eJOa}^Vw96>fmw=OTXp74XFlppj>MJXZoN=VgoP6g7c&k{=4!b zoTONn>xj|qa~|hiA)e2{Wa$)#Jm29K!>lr@Wo=tD+Mbqfpr748<6f4Hz5vyozhT&K zV?&>8i6&YszNO?dvPJu)lQ70o?N^Tt66xKbe6wO}YL75&4YPXUyh}S3%gc$KN96?c zd}#wV!4HXxYUApMAD&%E$gLUpu_Q_f%esF|=z-W1vgF10Y7GlQuJ(;&bh*cQ=;T@$ zmOcn_z3z431rIDZGQ)UMZsqpoLfh~yQ4o;;-q4KH4tK)pb{@CCw(z|x;TR~_Y!yY! zFqJTIY+Lcv9A)p+hMjO!p)J$ymQ8bAU4J%c&jBbkbvI(qR!X;OpEwT&NKSNWKwOFG z%0JploB|-oeDlh41FjKIJ`gJuLxvYY7DPc!4rEncjA^7=NLiXlWM(xU6Vu*1 z8xSlc(L}&v1gMaoD0AojMHU3A=I|qu z7oVn|C`gYhA9;W{e$5G?3-9Z~4lY7Rj%{~n3QG=Haqp6>JnPUp9`-pibPi8gF! zuDrR-A$VTefEcU@G%?c~Hw}^;Ua*zq$p=tv&M|ANR|#H+h8a^}rOB~#4-+Ixte`}R z^goG`)5rj$y$nAA9P}ib0bSbJI(qlI^2hH!+zwt4TZVT|#ua9cmd+-X``{;;9&NF3 zW9={xFl2NE!TdV_)|0U863r>rvrc)>CHuj>-xjojf}3ECmj-d5uCOul$c9se-Ds21 z6Ix-0!s{;=EX|ncK%WYGT^qzwG)O@5g1M8EF&2!De0F*)<7Ye?E1aL5XzQ9a^}(F9 z-I?T*V3o@bZMx6ZyQYw{`v;&B!8Q%VdO5}da*$rW zMjZUb)fiyL-o;Fjobxy5qzY~sPdW5ZvNVU!)asDLSfl*E>sr4}X*MS~^DItMC_tLP zGZTwczKf}{@fAf79b(ERBhBgdPS@~V`jZz@3oRc(Fq1z%xtwa9t*^d{ZwSl}_OI}0 z#F)kLQK(%`B6<)MGlg3g`_3z+E)yWf{{82E`!yDqUXQwZZ`>8wTM@I@`}>}RZZA@# zmP67sWw2?RYJw_6$rf8Jv{lPKs7HlSm$3yNjCdrBf+anzpN%eF15AAGf@3Cr?=c?2 z=tav@?2CJyF&WoF0ato!3o{9jSffwz(Y#+^Y#<)1xuVhwB;?Tl?$|Ipr!xdE$N@@Hc&FA$nqd3@o5ISW1V#0CNm$-xd2Obcn zKBWWBkHDXtAHaq9gWQ9}$Z>Hk(uVg1sBRX`J-ESOWIN`H7e8I6R~l(0G(0A0N6XhZ zIRNJ&GVcdCXU|!eruy7x-p>(AD36|h?dHulTqT5g;#aOUfNdCfQpi%v#t%rV+lj@k ztf7P-*}SW(Dk*10L_d1nTH$e{e^}s#b2VE0V6TmxPVX=EsKszi`K%GiES**>qaF<2 z?&g|sk1!CxN~mF9prKO#vG$qk+!8IRxE)Dxuw?2h1xiy@7)LYB$8W&JC`Kpr@sCyI z88yCSX^pU>1Zx#Jr^wwY&ScWuJ8+|k7%_?dfr3j19zm^l8?D*XGirV8+V;QDm zydfn;DTS^9lp!7^FGiQE1&WZ#yFjl!;%p%HmD#J2NgVaN-_DEDM)&B*+-$!)bS}es z^buD9O-@@*b(fRqims3mRQ?m7ilo6P*_Qa5ry15AsL{;J*jFu!@*cQ*2BD_+{ihRM zuu9HFwOzhTY@DhugTzNg11G?E;e+ECre&_I-RtBn6cga*jFfa+<;`x6VcmCY{*krj zyPd}d3mPA$()dfUi9|ZXJ5Tn1-#3gQtz3K{Cj>53L66Y;^WWe9{(5)eI{h{y{6iXp zexFAp!YqLmn4ZDrHWI`;AK_x{o9#$m9Udr)3+PAomim0rO@Ako7+`K!EN|ewu zfO;ZOV1qZ^=R%M@!@Wt8lVHWa2rCVH#O;b$TP-i7x#OQL>lnyT`QR_8_xUahnY_rV zD^88*>6SCH?Ty@QAx@?t3q|OqXF;_4Z_wZ(6XGN|=dgnL)$Ddf*#qUiY3QxrH|gb$!=_q=< zY~pxBTNn+|@zzuL7XDK-^3uL;IRR{NrDwrRBU8=sxELcUqJCc6KlE0!GT2M|H;kDK z1Dl=w>kG`{`}YRVJ0w~RRs{?*@~u&J2wagRAen7u&LJ6q+X~H?zEq{)QsYNI-VNvG zPwd57Azx>$X8#NdVbDNvRGa7xX&44NilL%65{8Y`(i`Ue>K!?`0&M zwa`$RXuuD-y3@gR`H{S@km<}Td(&)a%|H-){14;y4PBY^Wz(`(bE9}9q9)7*aN@~D zy^Qn)MNI=4I}TK;Eik^DVKJaDsxpC~>*eUjeu;A>x%8PN0k+cO#PVNh>=9_VW((JK;soZg$Xl33Npb*HBoT9`Nd;|tzdiGM*e}%->{o|DtwpndGN#4 zE|aZaaNJK+UbQHNX_i&HzJFO1$r45$b)(e@?zX+V{rTFz5P_(`QObPvJp8J%+t;NI z0f*vf^*fp;0>yvOOW+mFfjMT_d~S^X z)AwqD>d zumRfx%B|g8n_(v~kz<?dsZEV?8-5m8PYzjFBb5i+d3ORnhZEMi`aMwOhJl(UhY z-cf%~CF=io!8=9^m@fTa-;5ERzj!uhv4hfgzIpR*^FZ%{WxK8>%}K^auUSVOMAt$= zbnP&&v7RWfSP}24GGwxtHPCr_@?d<*y%r(nr@dqLaaRAg?ddNDVzKWXZ%__;kQ{tpI5)(_zK68X5k@2>g4v-oFKww1Vp$53tE$K zmDITmq|UftJ`H$0i+5P;_5Db?FxwG^M$Sl*Ta34+g?7d^UfgSb-Eg|?7nWd__~34Z z@7b>!z_H0#X3|`@*_p=&Z56XByF|Cyif9QudI#*RbYK}Tr-G3B#!Ax2cg& z>^(d%_WNYpY>E-3+D{btnt)?VxeL6d<-D*qC>8PB7Q=U-JB&bQv3}d)p7gIR?zq{i zZLErcC2##2ZXf4t!3Nwe96`2~_mLiM?)_o)O)C6Peq36ztmv-hvP`#%dyKFb7?u8l zKAjS}tFPI4eDE0S5=U~am!qObwKPWt>kG8+7B&fiVbnvdgnv5Jy0mdOQa5XF=lP9W XbvnT|zdcc~hyT~9bnHZR)BY3uf}P3+UmZ-7)-*fy^Q?`vJqwqAx+`2pcJ>?9tOoXPHyfMp zwzS@ByWjqxqqndBF=t?KXqYRQ7Y3f^*z@Pa#?6ZW&kHLdfs?=s=7qrq!Uac=kkrtZ zQZlv2f3kDt0)wxlmCX*Oo%&fubNR-eS)cBzm7TrNuz69hU~0mdO>Sc0&owjA#GcNp z5y;~(@Q;Th026Q_ovsbgqK&&=XzgGZ>r%F^qQuelcb${h!Q5C}QZ_F?8v->J-Fyg~ z9;(fOz!fS4_~i@XHyIAcdf&5YbRO8f`*p1#b2_rUfw?@%)b$}=HgI=5nk-_&A}4*?B$-*boJAz((f3Dcwb zbkH6XN+D43h;N9jkZtIIJuQ12u+mNslSPy@sV)%smIVRcp7jt&Q_FNA(}op1Ai%zu z$|W%UfjvbT`~WBW0MP_#pI4F$LC zzq@S|KYyYiqDs;fYKI~zERe)PX{-gyi&ioX0v<}Vc8hFQr3c>}77?6YEq)|5MR*f# zMw|TQy6j%0Y`<0#E=1dLI(kl0#ppg*GIZXx(v3vcW*udvNT)!>>Vi!9CAUB6-E zI3?vg^ZGeVanCBIm?fbmKISvxR)|=QwOSkJf%b^5<5N5IU*A0<)d*FIUR(j`3!M(5}-H*T7zOqlvl! zYN@0CiMQJ;BT|&spbFB|sD&aiJm#h73l*~{#u*beg6mLH+~`1?SY!*=1^*-Lu@idj zTDfA%`FLAGXv)cn8yzpT%|!hGg)&eKXPSUlB1H*>GNuT?5sBe3I0J<;5Vphf!Z;|D zfkGK5lz~DSZzqLBB!y8ZS0| z2?8@M8MM~zY05z!f^8lc=vZ>U-JCaCJ@7^e@fPNXQI46`W;JP?UtlwtNXQ0F;0b11_MjlZ9w z!~;gVxZFo%xr9yGtaT@W(hP7l%jBnJwEKN6d_J7TAd7azs*_)8(oc2^(}jSSI|Qol z{leqz=*<{08|2gUOu9R14CnMP!)5t-b#`Z*N>UuH&S5lwd{P9Wfm-xvWL`yQ0R)yi zWnrraqPj=koEMslAV)CMb&DmM@--G&Cn|HF&{A=J_@5d`n*SoA(>=$mMJJ7eycrIayL+;$NhWz^lOCjKS8&2ck z*3!R&uXC!ctd#CaDKGZToO|~CaxU96Yjfz~U)N)X_cvBJY)(<}uJS(fUX}0Awlx_x z-)tKUsW|-bF;zRg#CC?@?(4Be`7JNXZ+Sb=A!5$cUFdeQgVd)~0)f2h(Msn(nZc_O zr-oUT1}9fon$LX*f$J=)FgCGZ(jRy6U&=^Sz!4X!lI$G|6^CWE(Ab{*t!Z=%y3;`$ zRT~QBL%&NGAN+imNIXl;OHFjJ-BR4-`@@pE`tclcyzOC&!_Ef}xE`=Jp!>Gc_kX6Z zNN{)Z@VJ)NUT;rvy)KBm-_!pJ10^TpG81WVB68vz>*~r&Z0_F2$)D$=bc^BMcf0DQ z`S1T(v{h3p3TI@a*y4xkiLD~k+my| zJ|NZQ2IV6&4tT7)t+mfs&dV*b!Pb|ZbZ~K_%%96Zl`CH727IXN(0q+(~-oAGSua`cbGYKYS%^kXLaz7V$c}cCFg8Z zKamqi5L@$7!wubt^B@rE!qeg_?Rb>hJYq87nb2Lj7Xm}?=y$s!V^$iXqXVq*)+4q9 zP0=Prdn(Iqxqi2XKdS03G2Yf1@E|tif>QGL!wx$}a<%$OH}t9p8o3O_K;Xy@{_To^ zgrI;x62W)@?R+RN83IcAKk&Y;gg|2K%DueQhk5!1O}W0D3vr(?n|+nr8=T|H*p=l` z^>K%iDSsPS#Aa?42%K@I(_dvk2+0$ZnMiRdjMUUcirgHew9OJ`i4hmM&-!s(ZPt^l zFT?l8-8|1r4IdxA`@H>#DCUBN6qMk@*-R>-V=yam(CX_CqMVL|;db8fa}vL1#lnRB zF@EBgt5}WcZzolbb~#mRiO+j$<;T=Xv=H)GUJn^2H7PQrtYZ=HMtW7V)7Fo{??LJ; zTZDLFhy^!-&EndJSdE&ZjLDyV9ZtL=Uc!JV%Y)KtX$`xWovtQ`bM8=pfuU?JDf})u+Um!*3Tk5HsD#xKn+nR>{ zHO1qwsySLS8Yb{Bws@t}dAhtkg4bi^4U6W-GheD^j{OJ4-bigM&Dzm`SC>AAw85S- uYdCFKD3mVOQf6^oxkFEkYr%VyEg1GB8)L52PQKU4e!Fn=Q$7L=bo2j|Q!VQN diff --git a/data/temp_obs/1.jpeg b/data/temp_obs/1.jpeg deleted file mode 100644 index e524b578e708d0037d7413f576eeb5ca50668980..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23933 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 diff --git a/data/temp_obs/mod_img.jpeg b/data/temp_obs/mod_img.jpeg deleted file mode 100644 index 71df74113039525fc44ae150c5b154048c057ef8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23849 zcmeHP30PCd7M>6wiQq#Zphg4%S><6tQbd6W2v++9DIgUHxKzOKu!2xfi$MVwYDDYK zSE0lzBnq?!S_LF76!!%oMnFZBQVJ@YND|1sy~)#}nI8BLgIZ#BWp&fLhz+S$hLJqITzClf0dx2cY<_EVf3WrN^IB$Bq4_Lz|)$2giA znL7UI3q1*RiE2O%;BjU^O&5pP#i3Qe1pA&EIQa#hUN|+px`rl!NE)GqbtoML)Npvb znmS%XLtP!~or3)zsOxIznL2oA>iaJun8lGD*KN-untOhC%HX4#u8C6?$FC=iFdRK* zEXBgo%G$=(iTb|tRF`R9GrfIgeK31YKw!}P;ExxCEcs+#}m&ytc?txikN z*syWa=FBg5?A*0`&)$96>;vB%Jd|I+;U49clz#uivEyZ@&s63)gGw1UG~? z>l>Qy-EaA+_2;%<+PiytANM`!7l|b@xp0`A&#wOnHbgF6OfEHbb-X%3CKpaE32S&= zbq!MoO+62P!lF2RGsksAvgh`^?@p1-r+n09usFVEgyBS|W{Yl_XmZK^m|*K)Niv0C z&*f?W+ISo`d3aqw183No)&MqZ{84u1q+YKcnJ(}rsdEG7Wd)y@$uA3BaLe|{B`_`v zpUsgLb5L;2rxQWJ52BjGC^*MJ0a7^;`;Zk-eEq8MVs3*ZSE{}o1)T#-mWlF106W#~ z%S`L9)v%`HD4@>ubPMm(Lw@m(TEXSL2bR13gOUHFG9LvV~M*;sK;-vgQ_00rAI3m;|Ts?nk&per9%}yPm)TY~7v-wW639`@J z69p(}p)yerp~r0V;Rr5AAYQ>J=7=3Y99JJ#jGRWa8T z)%iNEYVB2?1kb-9L%OcX;Dg*E4tJ4ybrLv|l zQ=XPXtsS&E65i0xYH4WK8Z+QAR<~?;$t9vPzk)6K!M7xFbI{QjJbwj3L;m95B$)Hg4FxQeYvW*6rG$DcrBr+1O>68l>6ays?cw+h%r& z3{1m0d;Pu1xE6_uH699_ayME_6=7kY=VWA9^`rC2Q+|jqdUnG)R$dkx61}$3H9B&s zy36S;IrW7)4+fefT48HrQSjq@%RI~#n^Y`$fPzcHS^2k8xEEYV;?#yF|FE0;u8^kk z8qa?#`uEI(z9q~1L-;wDilw=0FzyqRb(t^Xp3Q#p$Y#Hxr1|t$%X^7eJLsBuaZf^R zCK6iB8Pd7&35)Vw4z-+dIn(@Y4{MqO?{+&9%JY;+9#XY-g>nQlj{v<<;CunCWHR&T zp8E)bakT>Gxj7w3Ijxr(Qsy^`C(XlNM%!c3-^Z`cdZ^VT9z2H8szQVsk_jF&o_d6? z`Y%KH;rAKfh)mXS_+C(te@i{q%ZQV#brd|kxm&6uCefL~C?v9|EqI(gMbq^IM|U=d zVbY^lhJvE2gO|O?Eb?KquN=S1%-r_#7n^I-s$AWY1$3JIp`7x#%I1XuRZFbeV=Qy+ zSayZxMm(eJrR3)G2BWGM8=F;dEBSjouPE6s0fVPxKaRA@=%E|sSu7_fktrS-fdXMw zu0)rcxDw-t+b}m@`uS`WQ=+AESQ&K+5&bUxm*Up{~ zNJQ{Sok_!Jey=zV<0YYk(RH*Ii$oOAbH&+(GYpwZkfDqbhy7Z*4ZJ80zQ8oqm+zmt9$CoC0la14Bhtr zf<66nzL=g7v@aDOcXwqFt+bCOA>Kwo(-Ra>R2EJGZskBk01CclHAzwMY4-t@CvL(# z%}O{V)FoU*ueN&#M=|CBWb8xu?BHdISt!_ipqk&~9Kmd)NexTaMdU78QDWga@>KXm z_JhO=zMTO~L_cB_R(I)zf(d6)P<7*M#-RU^c6alVlJbh)2|L#Q)Uz#$SQW3idR>_J zr=m%SPlw6CG8C{Iw#+w7kDgmFss1s2y<<{Hj>VrWL|MB&{{N!8*D@h+(6?mgyyFw4 zD6^F16UhtGhO69CqOWXd==@CA$ucuiUS7h(%t+*o-g!~Pue*F#r+tiqu8ic3$T}2= zDKx~E?|%ATfls=A_K7_~H#>IH@1!m6-g-iNHaST&a~{`quLz&tRa;?z0`tTyDOO5T z6FY0rG+bukn1~N%;W7)ev_ugLYAa?fOG=9R>6Eeba%*0-f9hSMJ~Linuoi`C;7o2< z6H3R~(8I+1A@)01B{4KnVslPb9TcWgUpTa8RbD^@ySz}#`$zTi;v#(Wt0EP}W2<(< z5F8A_!4TZ5h2UO8V!eW|$uf@RS;xaw^Z2}8?|dJuJNYZ>PX0)Sv*I_Pw~)6fkk9zd zM?84206d)GZ+RYt!j=1<&H?a!*Rf*pXo7NQisW z5pcK>6^{32c{p$Se3*Rb?` Date: Thu, 24 Oct 2024 01:44:26 -0400 Subject: [PATCH 3/7] done some parts --- .gitignore | 1 - configs/data_generator/config.yaml | 3 +- .../__pycache__/data_generator.cpython-39.pyc | Bin 7874 -> 7979 bytes data/data_generator.py | 20 ++-- data/utils/controlled_reset.py | 22 ++-- frame.jpeg | Bin 0 -> 23463 bytes script_gen_data.py | 108 ++++++++++++++++-- 7 files changed, 123 insertions(+), 31 deletions(-) create mode 100644 frame.jpeg diff --git a/.gitignore b/.gitignore index 36b7e37..7063d26 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ -./data/temp_obs factored_ssl __pycache__ diff --git a/configs/data_generator/config.yaml b/configs/data_generator/config.yaml index b4a8b6d..5c2050b 100644 --- a/configs/data_generator/config.yaml +++ b/configs/data_generator/config.yaml @@ -23,7 +23,8 @@ state_attributes: [agent_pos, agent_dir, goal_pos, key_pos, door_pos, holding_ke state_attribute_types: {'agent_pos': ['coordinate_width', 'coordinate_height'], 'agent_dir':['agent_dir'], 'goal_pos':['coordinate_width', 'coordinate_height'], 'key_pos':['coordinate_width', 'coordinate_height'], 'door_pos':['coordinate_width', 'coordinate_height'], 'holding_key': ['boolean'], 'door_locked':['boolean'], 'door_open':['boolean']} #options: [default, random, custom] -reset_type: default +#reset_type: default +reset_type: custom #options: [agent_pos: [x,y], agent_dir: [int], goal_pos: [x,y], key_pos: [x,y], door_pos: [x,y], holding_key: true/false, door_locked: true/false, door_open: true/false] #agent_dir: 0 - right, 1 - down, 2 - left, 3 - up diff --git a/data/__pycache__/data_generator.cpython-39.pyc b/data/__pycache__/data_generator.cpython-39.pyc index 862cbe3d4a09aec1d4999b35fe9f5413b5b9166f..30a0db83f7f8c0944d6caee940a964f616dba3a4 100644 GIT binary patch delta 1878 zcmZ8hO>7%Q6yAUDuI-Kg;>L;NCLtwq(}qGz|0zjHi;CKmw5WnW>u$1Z$8PO)XD2@` zYa&rjNWCyZ9DrhT-~a~%YGvwr}SL)+aGj15<|KPqXi0GaG^ACC!a%z!L{gBH9D2B!5GOW`V>0e7_t< zb~pNaf+)~DOjv(UY{7}f0K9U*>2p%FP?a72>c(JW=s#95vYa%3X5LU>&2S)eOR$?< z5PEp*t$eo;U@&0cQD88DjR70e9O0}`&azOSU~e1wSB&0CB7!siEc7bAjN8+b}dKki6ZuKUpK|Q&_dmGPv~fl2B{Vr87BrAdKbJ| zJ|BY=%8q_m2sC&ahoSGC_)B1Qb3I`ei%5f2{Sc)EG57+=P$+sJS0(7OXAp$y$j(8z=Bn^m#9Zvr$SucrJ=FXS|gZzhaAPASp*aY+VM(%ewoXzf*l%F;x%nT z?5m;T+p8{_#;7Jjln`Vs1P`GNP&T5XSqC0Ul?qwG8O&KI*PFF_i6g6cjS)QS9T@)o z0D^(dydByZiU-n?NXccHEuKz#ZsEGvME70VZf!9(`gBdAu z4cSq~3X|dt`?N5r@%lN>ek&BRc$2#@{BZz5Qskn@ii0=fSexWYgn4#*aL0CRx6nAY zzT~#C)ti|}Ef%j6)N9KJowYlK%8Ptfxi_X0uyz;dOLety_hbP)s}fwB{&r^FV! HSsMQfXRf+G delta 1865 zcmZuxTZkKF6rNiqb4jvE_L^+k-PY6^yY_1DwXN&6YK86A)uLf{<81y(HffW|{xf@N znXqDg5V27Fp?#=I7C{B^K?^FV2#OEB3BFC=d{7I5AVs8tc+NjdYZnvFm+zeaod0qz z`S9pBk0q>l+z{Y%`&y=&ANe@(MbwCZDucKZ`!V|Xif7bKUm{9IAQ7TomVBWU^Wwfx zk6jWuPu%0+7tIK$m%4y!5Th>$^s1Lc8(0jmnBg9v#n88u^3uRzf4*NgdUkqN1yS&N z!Tw}?ZJ`er>irM^(iwoIL`GP}D`fae78nTl3<3iImIIa}!lY2>VgveCc2@7Oqk6wo z*uX}O;|~UM^+F?18rC_R_P~p&f`D(QI}zdtyVys@VKKvAPGs12^Q`d@7zHUIr)74< z%t=XweQp*KCK#h2Pk^|8vER)DD?bs5sGeSt3FNFU)*+AgX|YfvQU0sFrL<+tYbUWP zbh=g{8*Rmlc9K4h_eWb1Xvaf?~fM?2&_{K>hL4G72 zn(|fOAS&0@`Of?mPp&KV2)MxoiGEq0#G(nrI49BDUYeMf#8*U~w;1~}ws-QD2+z8O zi76;Sbk=ds+g7ufEISS*wWj6SrKKA2=8CERSmx|nb3*)bEvsz1MS0X&reo-nMRR1K*7ObpGGL%oX^jLCesG|M zr?J=KTeLv6S}oX%eI4)1o3tCFck}29wHkIY2}LjQ{YxziEH3*cK9fHJ9!ntZFn}N% zq9G1QhO}EsNp`06Dc}Voe6Zqrc8kZ*!|b0_R-J@Jx{qy47k9pZbPfR{0@ImwZMtZAHK!S# zckj>|I9z8Rq{k8(FcpON;1BFhy0L;&(24sBw2%_ERy#r>Z58ZYM1^W!1#6P8Lu2_e zi5?N4D`cV_fzc(#tDtpKtHKzzV+5ko;00X+Lo7oJMt!*=!F0tgerpV`eV%T%7CiUR z@VL{o*`4lBhl*->!S$R59fZ5lDS&bQDmsJuG`rbz=7AE@S%h^dwZZlq+AHjI?;|T! zpoQ*mSP!9j2f{&sVxnS|J%`$)L~Ymh0)3&mM6nYHJ&jIh5GD|Ip?k7KttN3AwTpHb zuvQ6ls3U~cKz0t{Ji?0&z=9SQe*t(Pl}eQ2()|^qF51?;1uy(Ph`Sj;(9_Ul4?~-2 z&}JHQ`=&Dg7leoZapTv%Noi9VXdo`H-xgE!HwdI?DswIQJW~E|wutOBle62zakeA7 zP2~+$WG`hi-T1mcLEJomASrTAVsB*MF^_{rPa>RRdk05GaXth6#B$kgVe81}P&~$7&uuoJ0tf0L%&^aL+r?@2bB>z((ZG9c4=ZoT_dJUFS%4sF z&BEM!b967ezTvw(zXfkXtYDy5sMD}0wJyLPOrshouC-{h_Qv5}erH}B2lr|r%(G86 LJ}1tx=urM&;U}$& diff --git a/data/data_generator.py b/data/data_generator.py index 9d98114..1ed959b 100644 --- a/data/data_generator.py +++ b/data/data_generator.py @@ -77,6 +77,7 @@ def __init__(self, config_path): # Configs from the yaml file self.observation_type = configs['observation_space'] self.state_attributes = configs['state_attributes'] + self.state_attribute_types = configs['state_attribute_types'] self.reset_type = configs['reset_type'] # Create the environment @@ -94,7 +95,7 @@ def __init__(self, config_path): #Store the controlled factors array self.controlled_factors = configs['controlled_factors'] - + #storing the custom reset function if needed self.custom_resetter = CustomEnvReset(configs['environment_name']) @@ -106,10 +107,15 @@ def __init__(self, config_path): #creating the observation space and actions space self.action_space = self.env.action_space + + self.gym_space_params = {'boolean': (0, 1, int), + 'coordinate_width': (0, self.env.grid.width, int), + 'coordinate_height': (0, self.env.grid.height, int), + 'agent_dir': (0, 3, int) + } self.observation_space = self._create_observation_space(configs['state_attribute_types']) - #creating other gym environment attributes self.spec = self.env.spec self.metadata = self.env.metadata @@ -124,9 +130,7 @@ def _create_observation_space(self, state_attribute_types): return gym.spaces.Box(low=0, high=255, shape=frame.shape, dtype=np.uint8) elif self.observation_type == 'expert': - - gym_space_params = {'boolean': (0, 1, int), 'coordinate_width': (0, self.env.grid.width, int), 'coordinate_height': (0, self.env.grid.height, int), 'agent_dir': (0, 3, int)} - + relevant_state_variables = list(self._construct_state().keys()) min_values = np.array([]); max_values = np.array([]) @@ -136,7 +140,7 @@ def _create_observation_space(self, state_attribute_types): for t in types: - space_param = gym_space_params[t] + space_param = self.gym_space_params[t] min_values = np.append(min_values, space_param[0]) max_values = np.append(max_values, space_param[1]) @@ -219,6 +223,9 @@ def reset(self, seed=None): #add the visual observation before augmentation for debugging info['original_obs'] = frame + img = Image.fromarray(frame) + img.save("frame.jpeg") + #apply image transformations if needed frame = self.data_augmentor.apply_transformation(frame) @@ -249,7 +256,6 @@ def _construct_state(self): #extract the types of all tiles in the grid: useful for goal, key and door position types = np.array([x.type if x is not None else None for x in self.env.unwrapped.grid.grid]) - for attr in self.state_attributes: if hasattr(self.env.unwrapped, attr): diff --git a/data/utils/controlled_reset.py b/data/utils/controlled_reset.py index 6fa970d..31dd8db 100644 --- a/data/utils/controlled_reset.py +++ b/data/utils/controlled_reset.py @@ -12,13 +12,11 @@ class CustomEnvReset: def __init__(self, env_name): custom_reset = {'DoorKey': self._custom_reset_doorkey, 'LavaCrossing': self._custom_reset_lavacrossing, 'FourRooms': self._custom_reset_fourrooms} - for k in custom_reset.keys(): if k in env_name: self.factored_reset = custom_reset[k] def _custom_reset_doorkey(self, env, width, height, controlled_factors): - #change the random seed locally curr_rng = env.unwrapped.np_random local_rng = np.random.default_rng(int(100*random.random())) @@ -34,11 +32,11 @@ def _custom_reset_doorkey(self, env, width, height, controlled_factors): env.unwrapped.grid.wall_rect(0, 0, width, height) # factor 1: control goal position - goal_pos = (controlled_factors['goal_pos'][0], controlled_factors['goal_pos'][1]) if 'goal_pos' in controlled_factors else (env.unwrapped._rand_int(1, width - 1), env.unwrapped._rand_int(1, height - 1)) - if goal_pos not in used_locations: - env.unwrapped.put_obj(Goal(), goal_pos[0], goal_pos[1]) - used_locations.add(goal_pos) - + goal_pos = (controlled_factors['goal_pos'][0], controlled_factors['goal_pos'][1]) if 'goal_pos' in controlled_factors else None + while goal_pos is None or ('door_pos' in controlled_factors and goal_pos[0]==controlled_factors['door_pos'][0]): + goal_pos = (env.unwrapped._rand_int(1, width - 1), env.unwrapped._rand_int(1, height - 1)) + env.unwrapped.put_obj(Goal(), goal_pos[0], goal_pos[1]) + used_locations.add(goal_pos) # factor 2: control door position if 'door_pos' in controlled_factors: @@ -46,7 +44,7 @@ def _custom_reset_doorkey(self, env, width, height, controlled_factors): doorIdx = controlled_factors['door_pos'][1] else: splitIdx = None; doorIdx = None - while (splitIdx, doorIdx) in used_locations or (splitIdx is None or doorIdx is None): + while (splitIdx, doorIdx) in used_locations or (splitIdx is None or doorIdx is None) or (goal_pos[0]==splitIdx): splitIdx = env.unwrapped._rand_int(2, width - 2) doorIdx = env.unwrapped._rand_int(1, height - 2) @@ -58,6 +56,7 @@ def _custom_reset_doorkey(self, env, width, height, controlled_factors): env.unwrapped.put_obj(Door("yellow", is_locked=door_locked, is_open=door_open), splitIdx, doorIdx) used_locations.add((splitIdx, doorIdx)) + # factor 5: control key position # factor 6: control holding key # pdb.set_trace() @@ -70,7 +69,7 @@ def _custom_reset_doorkey(self, env, width, height, controlled_factors): key_top = (0,0) key_size = (splitIdx, height) - env.unwrapped.place_obj(obj=Key("yellow"), top= key_top, size= key_size) + env.unwrapped.place_obj(obj=Key("yellow"), top= key_top, size= key_size,max_tries=10) else: #need to set the agent property as holding key env.unwrapped.carrying = Key("yellow") @@ -78,7 +77,7 @@ def _custom_reset_doorkey(self, env, width, height, controlled_factors): # factor 7: control agent position agent_top = tuple(controlled_factors['agent_pos']) if 'agent_pos' in controlled_factors else (0,0) agent_size = (1,1) if 'agent_pos' in controlled_factors else (splitIdx, height) - env.unwrapped.place_agent(top=agent_top, size=agent_size) + env.unwrapped.place_agent(top=agent_top, size=agent_size, max_tries=10) #factor 8: control agent direction if 'agent_dir' in controlled_factors: @@ -89,7 +88,6 @@ def _custom_reset_doorkey(self, env, width, height, controlled_factors): env.unwrapped.mission = "use the key to open the door and then get to the goal" #reset the original rng after resetting env env.unwrapped.np_random = curr_rng - return env @@ -162,7 +160,7 @@ def _custom_reset_fourrooms(self, env, width, height, controlled_factors): env.unwrapped.put_obj(goal, *tuple(controlled_factors['goal_pos'])) goal.init_pos, goal.cur_pos = tuple(controlled_factors['goal_pos']), tuple(controlled_factors['goal_pos']) else: - env.unwrapped.place_obj(Goal()) + env.unwrapped.place_obj(Goal(),max_tries=10) env.unwrapped.mission = "reach the goal" diff --git a/frame.jpeg b/frame.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..8eba486f5827ae9bd635fbaa722f36cf5c45fa80 GIT binary patch literal 23463 zcmeHP30M=?7QRVxi3lPpsFju_RVWx10mTmi*$P6bt+K?5qEJA^parS4JQSfQ z7Fkr5ARt8);QA6No{galqfoPfvUB_#<`G77RX($X?Bih-TItv#Wl0IF!%*fbsg_X6<%2l>b&MvNQpSyc}yteUs_dtvF6g{D_4KJeTUAdZ@7D} zvH5XJYg_x1j;GAtz85c9{R4wTY+k=Ga6iY6KRPDVFCyG8te6;14A1Kq1{(sOIHH)i zrk;enxg&mk;EcKYdk6{^2h$6GmDDm=+oSl^wp&t4^9-Bk_wu?n+OzR>Z0|qn8NXw% z`qcAPY_z5hNDcBs!KK@FaS=TYYeg zM{j-Mk`hMul4s8oOfOcsex)DkU_gJwwJza!b1mHj4Tv2K0ka(7F`nF|weo4zjO7&pW~U=x%2l2`_T%I93tOS{LRUq3nZ7BB?eKQP_We!KeKE9}|Z?+<-m*Il~&o7Ui`aXYHzkDeHE z+A^G{-B-4{S1rWUt$#lRj%?vRtn5z=4Gz&DE}u)S3g;Y!fPBGe&JVQ^NQzs!o0Ix1 zU$3YsZ!4=hem$*ut3pS;YkYY_ZABD4KH;d%FOF7<%p*|>j%MoiLP{<-8S!`wW1y1} z1I~}5PQNWYr+D*f>@>ON%peh1JL#*3Pgl=K+U1XQT1;JwZZs$YQ;!&nFB zjkbu6<0}IUojtI8{+-O+;|VbDe6hsInXbj?cKo<2Q7J?!*8oVgTxh3J5em~#P$hI= zpY&H`LBM=gH)l2X86Y3lrZA>DsD{G^@Sr`O-hQV zkaNcKmBee&Dib#@c-X;E06gcp73u9TjDU zF*hZQIKGPG;}xkw-i4chV-YmEoC$j%Xq_?VOtj;}gI|FHe113oC1hWtRVXPU z9G9K*VepR!0HPrbG|Ykqm&RBr?_p4cZ@5i}wQytfezuXb_Le7E-R(?Bd6)@-kp&f+5J-#Wn#Vz4e_ovQ;Bj~QE*pRU zkg#_11)OVbbLxoSx5}`vB{5AsZX>bvrGz)8V7FmOmcHTrgr< z`Fi9l8B!JnEIiYHwiLUz^!$t6Z-(tUUpgH?nPn*Z?eFoTiY+C3(bvn-vvhb{1`}%wWgGKr9mIQ{)ge3@I9Y@}&^SzcEtl znkG$dRIYq66bL6CtQ+w|-q9sHO;%cD&qOaNE8XnjxBI?{pU*}yqpBZ|-OH1EHr&LP z_T0T00yVA+5FKo=$@)E<_M4I9P()*sqvzctb&|`9?q5AU_|1xwYt94=cvK#{UcgC( zN5FhjTy5nb?Q(K|*TNJfc5~Iw0WSzQI=v*)1N+x4oQH4MqHyfC1+C9A%51GRs%}2r z7i+9n^nl4-S7gCvKPO2iuFGMpI0fXVgR9x(Gapl*^tEugaJE)9^@?pLw~YLPjUQWik9h;k(&&-M{L0QE2pG7~>JWkhuM9jxxCk+OPcf0=&Wkun8;}3; z5Q~y~TW{(;Hb2NxTIFOYQ-iXLN?hCzgQeH`*?9IBV)&$*pZ*X-i+CHOs5jbV@21|(J>`wVyrZYCm7 zqNFHb3MPGne6b1>y*N#PO5^JvzF9Y(L^U}Vq%k(7%y0n>^xBi-Q{U~5F|Qy$(a@-0 zce*x;T4FkrQ0qF+?8EdwY9<2An-KJ2LK@{um%7NMO5}=-uZQ^N-FOnna0~>bA^>jx zflg1TLH#$#_`kb1imSuh#Gtr3iuAuJ8Zy~&b&b{Ver-ePL!O;EBM#vwsDiusvdQ3Tox9@S?-hK83&EzR^$xe-}|+B46c?MKQ)c cX9xco))@O?yq{{Z|L{WL8@&4`(17m!57z}W82|tP literal 0 HcmV?d00001 diff --git a/script_gen_data.py b/script_gen_data.py index 4bfca60..1cfcd8f 100644 --- a/script_gen_data.py +++ b/script_gen_data.py @@ -37,18 +37,18 @@ def sample_episodes(self, policy_net=None, optimizer=None, num_episodes=1000, sa episode_dict = {"obs":[], "info":[], "action":[], "reward":[]} done = False steps = 0 - obs, info = self.data_generator.reset() + obs, info = self._get_reset_data_generator() episode_dict["obs"].append(obs) # obs: image, expert, or factored episode_dict["info"].append(info) # info: everything, regard as learning target for obs while not done and steps Date: Thu, 24 Oct 2024 03:24:22 -0400 Subject: [PATCH 4/7] done --- .../__pycache__/data_generator.cpython-39.pyc | Bin 7979 -> 7923 bytes data/data_generator.py | 4 - data/utils/controlled_reset.py | 34 ++++-- frame.jpeg | Bin 23463 -> 23902 bytes script_gen_data.py | 100 +++++++++++++++--- 5 files changed, 109 insertions(+), 29 deletions(-) diff --git a/data/__pycache__/data_generator.cpython-39.pyc b/data/__pycache__/data_generator.cpython-39.pyc index 30a0db83f7f8c0944d6caee940a964f616dba3a4..0aa583105a8ac1c062eafb838461601f14a96d31 100644 GIT binary patch delta 326 zcmZ2&_t};&k(ZZ?0SG3)l}vxCvytzf5FZDS%Lc^GKwNxb@-Ly>`Wl8To&~%$EDITH zS!x&-@GWGhWldqNWdn-yr?6!+6-@(*3V`L=YFKKRQ`l`7YFL3ZhYdptX9`yfkhef^ zA%hD;Gh;0)P?r!;6>AM!3U@DaEqe`n4Rab(FoPyf)nP6LDDccHC@m?rQt->qOP%~n z_{8LMBGrr^CVPpRGYU^`5{;hxSyWk)qevL&$f61$af>NFzNi$$iv|*tO~f>Wm4FNe zP9bJ4MlD7zMh+$}CXUI)VkL~Y5Z&4PUUL_7$wd=2T13&HRzjMnh58FDE#zdAVC14)f?%?zg*Fyei~U{a z2MBVloj*XZJVX%u2dN?mt{Hf5cyHbeGgyDzuw2t5NYrgoXjWIAtxwxBgj5B#1UldR z$M!C|snBF{1cAbo(4tBNfEa3}!|{Si#$+Z@y@r@7 zx=}-v(6K9_!d!&5(Io_`*m6WlWg1Q0NP*6DCN=ObS~7dDguiD$Qa#e}U9Y~{I;l7L zQ?3sKUU90B=LgQ7qljM-@zjgTcR?NhOgEy(S+zixUeXi40pJ zPyqruCRhLnU(0u47~kjH7-NVFg?WHqzFC|FIo>bI05hCU-6_kutk1=n=@L%+eR0S? Q|0gDh@06~g&EHDpKX0m7(*OVf diff --git a/data/data_generator.py b/data/data_generator.py index 1ed959b..7fd119e 100644 --- a/data/data_generator.py +++ b/data/data_generator.py @@ -223,9 +223,6 @@ def reset(self, seed=None): #add the visual observation before augmentation for debugging info['original_obs'] = frame - img = Image.fromarray(frame) - img.save("frame.jpeg") - #apply image transformations if needed frame = self.data_augmentor.apply_transformation(frame) @@ -268,7 +265,6 @@ def _construct_state(self): state[attr] = self.env.unwrapped.grid.grid[np.where(types=='key')[0][0]].cur_pos elif ('door' in types) and (attr == 'door_pos'): state[attr] = self.env.unwrapped.grid.grid[np.where(types=='door')[0][0]].cur_pos - #other attributes like opening, holding, locked etc... elif ('key' in types) and (attr == 'holding_key'): diff --git a/data/utils/controlled_reset.py b/data/utils/controlled_reset.py index 31dd8db..7681443 100644 --- a/data/utils/controlled_reset.py +++ b/data/utils/controlled_reset.py @@ -51,8 +51,15 @@ def _custom_reset_doorkey(self, env, width, height, controlled_factors): # factor 3: control door locked / unlocked # factor 4: control door open/closed env.unwrapped.grid.vert_wall(splitIdx, 0) - door_locked = controlled_factors['door_locked'] if 'door_locked' in controlled_factors else True - door_open = controlled_factors['door_open'] if 'door_open' in controlled_factors else False + door_locked = controlled_factors['door_locked'] if 'door_locked' in controlled_factors else np.random.randint(0, 2) + if 'door_open' in controlled_factors: + door_open = controlled_factors['door_open'] + if door_open: + door_locked = False + elif door_locked: + door_open = False + else: + door_open = np.random.randint(0, 2) env.unwrapped.put_obj(Door("yellow", is_locked=door_locked, is_open=door_open), splitIdx, doorIdx) used_locations.add((splitIdx, doorIdx)) @@ -60,19 +67,24 @@ def _custom_reset_doorkey(self, env, width, height, controlled_factors): # factor 5: control key position # factor 6: control holding key # pdb.set_trace() - if not (('door_locked' in controlled_factors and controlled_factors['door_locked'] is False) or ('holding_key' in controlled_factors and controlled_factors['holding_key'] is True)): - + #if not (('door_locked' in controlled_factors and controlled_factors['door_locked'] is False) or ('holding_key' in controlled_factors and controlled_factors['holding_key'] is True)): + if 'holding_key' in controlled_factors and controlled_factors['holding_key'] == 1: + #need to set the agent property as holding key + env.unwrapped.carrying = Key("yellow") + else: if 'key_pos' in controlled_factors: key_top = controlled_factors['key_pos'] key_size = (1,1) + env.unwrapped.place_obj(obj=Key("yellow"), top= key_top, size= key_size,max_tries=10) else: - key_top = (0,0) - key_size = (splitIdx, height) - - env.unwrapped.place_obj(obj=Key("yellow"), top= key_top, size= key_size,max_tries=10) - else: - #need to set the agent property as holding key - env.unwrapped.carrying = Key("yellow") + holding_key = np.random.randint(0,2) + if holding_key: + env.unwrapped.carrying = Key("yellow") + else: + key_top = (0,0) + key_size = (splitIdx, height) + env.unwrapped.place_obj(obj=Key("yellow"), top= key_top, size= key_size,max_tries=10) + # factor 7: control agent position agent_top = tuple(controlled_factors['agent_pos']) if 'agent_pos' in controlled_factors else (0,0) diff --git a/frame.jpeg b/frame.jpeg index 8eba486f5827ae9bd635fbaa722f36cf5c45fa80..4165a88fa83f914a99a2b721caa994de5d6f42eb 100644 GIT binary patch delta 2266 zcmc(gYfuwc7=|~bt%e|%O2wiCQV^nm!6^tL8bAp*fp7_zATTXrERG^m@k(8bRlpI7 z9H+K|A|N*-iFSoxM36BRFNJ`j5m2s0lz^aI17Wutt8|Cb_NPCd+4JL^J>U19_dTab zOlp&mF2|9nWMSTM282US1@j#|G_);|*QN>*xNa*zZqhcAfXsqIn3M!WK1Se}?=Fxt zKMtU}6oC1<1B`w`|KKuxf9H>Jj1t}rmimC2^&Y_5c?hJ3a^4XJKL-8&C>AM(?|3QD>#Sir-eFBf-eD&U0(wk2Ffa-PmK&B4Un4c~X`MMTqJzS2T^o7WfsfSt@3Uy|ajxwNdN(G#CX7AVoZrWu4 z8ka(y7vZMQA>qth2*hqi@Hg_4PLk3Gw@=jdvLOCMTDZ8OFwypvDeVaGcRZOat6{q~JhdDrPSE?#7sJaxj9hWraarqSzPIK!oi}|C%q;|jZvYK?8@Tt1Hmj-n) z=)PD*oeZ{-mejeKK9FvCaI3R`ccCn}@j$_~p2@MT~3yJc7ZD{CbN|1 zB7OlR62Jod3Gm>ACVw|bA7|I;%t~JALw0{@FUzD`UAcVgCaV`_wEQDMWjabq1T5#H zTLnSB+5Fe0MLH)$$$JYd4@Jd44)0qe57oOvh7&66&UP6q_h8WXu$Q!`^1;1}!v30X z#TE{izB6KnkDQwatMWvaShfg{mcZ-XTR#yWDfDZm1I zZ#*}r)VZN*OO7+nYv5>`gOzI-CWoysXj>!($$Dz1r{iAd6Wkh%H(83r)Bbpy#!Pw< z(qXWPgf~n43l%hm@d*m4)!GAenHeD7bITkJs2iFl1XCT*WW2gIVyeMuo*oGC3m^zG z;}XM>GJXH3GsYR}&@bJAj|*}{NAWQ&CNq#T$BJZv{O?n1uKzNYkymZYGI@KHE%?}* z6$NruKKqZd)up>SiZ)I73Hn$sKd-7-I~uXx{26@>dw86=E`454q+jIep?s8wK~MNT z7}PS_)4SYB>){(!<8IU}{s3?eT}74`yMQNb<9{e)=0gnh`(VHS(j9IvJKa@f7<9Ql z3xmoOb(T$4y1dO1(}Mn?%5%PgB5(7?v&BxTD`TJa^jceKwf?o~{(4}&fksv|nSfkP z#;jwqMyyu3Ys_4^h|EHpMDz=S>ei6p?FADDJ8x{S;}yFs}mfB$Mp((UyP?2S9KuH-~l437+)>8M-r z_41BBZ!MAS)u~aHW|FUWRxo`l^+Ji9lozg3XnE}fJwDa1uIAhuU`pekjz+aupfS}`2XOmvJ0Cqw z+&GbnL6q^aIF(n`tudxO8cBD0HZ=zST5(%;sO*+p+w+*<=*__VFrL?V)aprt0Iz@@ zAf91Ni7fe9eY^CZ0=z)0IU>MBb{nxY)bA`Y+2ArAo$KEFAFJTu)q~Zy$_FIzgKe&Z GHU9}2ix+PI literal 23463 zcmeHP30M=?7QRVxi3lPpsFju_RVWx10mTmi*$P6bt+K?5qEJA^parS4JQSfQ z7Fkr5ARt8);QA6No{galqfoPfvUB_#<`G77RX($X?Bih-TItv#Wl0IF!%*fbsg_X6<%2l>b&MvNQpSyc}yteUs_dtvF6g{D_4KJeTUAdZ@7D} zvH5XJYg_x1j;GAtz85c9{R4wTY+k=Ga6iY6KRPDVFCyG8te6;14A1Kq1{(sOIHH)i zrk;enxg&mk;EcKYdk6{^2h$6GmDDm=+oSl^wp&t4^9-Bk_wu?n+OzR>Z0|qn8NXw% z`qcAPY_z5hNDcBs!KK@FaS=TYYeg zM{j-Mk`hMul4s8oOfOcsex)DkU_gJwwJza!b1mHj4Tv2K0ka(7F`nF|weo4zjO7&pW~U=x%2l2`_T%I93tOS{LRUq3nZ7BB?eKQP_We!KeKE9}|Z?+<-m*Il~&o7Ui`aXYHzkDeHE z+A^G{-B-4{S1rWUt$#lRj%?vRtn5z=4Gz&DE}u)S3g;Y!fPBGe&JVQ^NQzs!o0Ix1 zU$3YsZ!4=hem$*ut3pS;YkYY_ZABD4KH;d%FOF7<%p*|>j%MoiLP{<-8S!`wW1y1} z1I~}5PQNWYr+D*f>@>ON%peh1JL#*3Pgl=K+U1XQT1;JwZZs$YQ;!&nFB zjkbu6<0}IUojtI8{+-O+;|VbDe6hsInXbj?cKo<2Q7J?!*8oVgTxh3J5em~#P$hI= zpY&H`LBM=gH)l2X86Y3lrZA>DsD{G^@Sr`O-hQV zkaNcKmBee&Dib#@c-X;E06gcp73u9TjDU zF*hZQIKGPG;}xkw-i4chV-YmEoC$j%Xq_?VOtj;}gI|FHe113oC1hWtRVXPU z9G9K*VepR!0HPrbG|Ykqm&RBr?_p4cZ@5i}wQytfezuXb_Le7E-R(?Bd6)@-kp&f+5J-#Wn#Vz4e_ovQ;Bj~QE*pRU zkg#_11)OVbbLxoSx5}`vB{5AsZX>bvrGz)8V7FmOmcHTrgr< z`Fi9l8B!JnEIiYHwiLUz^!$t6Z-(tUUpgH?nPn*Z?eFoTiY+C3(bvn-vvhb{1`}%wWgGKr9mIQ{)ge3@I9Y@}&^SzcEtl znkG$dRIYq66bL6CtQ+w|-q9sHO;%cD&qOaNE8XnjxBI?{pU*}yqpBZ|-OH1EHr&LP z_T0T00yVA+5FKo=$@)E<_M4I9P()*sqvzctb&|`9?q5AU_|1xwYt94=cvK#{UcgC( zN5FhjTy5nb?Q(K|*TNJfc5~Iw0WSzQI=v*)1N+x4oQH4MqHyfC1+C9A%51GRs%}2r z7i+9n^nl4-S7gCvKPO2iuFGMpI0fXVgR9x(Gapl*^tEugaJE)9^@?pLw~YLPjUQWik9h;k(&&-M{L0QE2pG7~>JWkhuM9jxxCk+OPcf0=&Wkun8;}3; z5Q~y~TW{(;Hb2NxTIFOYQ-iXLN?hCzgQeH`*?9IBV)&$*pZ*X-i+CHOs5jbV@21|(J>`wVyrZYCm7 zqNFHb3MPGne6b1>y*N#PO5^JvzF9Y(L^U}Vq%k(7%y0n>^xBi-Q{U~5F|Qy$(a@-0 zce*x;T4FkrQ0qF+?8EdwY9<2An-KJ2LK@{um%7NMO5}=-uZQ^N-FOnna0~>bA^>jx zflg1TLH#$#_`kb1imSuh#Gtr3iuAuJ8Zy~&b&b{Ver-ePL!O;EBM#vwsDiusvdQ3Tox9@S?-hK83&EzR^$xe-}|+B46c?MKQ)c cX9xco))@O?yq{{Z|L{WL8@&4`(17m!57z}W82|tP diff --git a/script_gen_data.py b/script_gen_data.py index 1cfcd8f..7302e90 100644 --- a/script_gen_data.py +++ b/script_gen_data.py @@ -5,6 +5,7 @@ from tqdm import tqdm import numpy as np +action_list = ["left","right","forward","pickup","drop","activate","done"] class GenerateDataset: def __init__( @@ -29,6 +30,8 @@ def __init__( # episode (o0, a0, o1, a1,..., on) def sample_episodes(self, policy_net=None, optimizer=None, num_episodes=1000, save_features=["obs","action","info"]): print(" Sampling episodes...") + self._set_data_generator_reset_type("default") + do_random_policy = True if policy_net == None else False samples = [] @@ -82,16 +85,13 @@ def sample_episodes(self, policy_net=None, optimizer=None, num_episodes=1000, sa # pair (o,o',factor_k) def sample_obs_pairs(self, num_pairs_per_control_attr): print(" Sampling observation pairs...") - #options: [agent_pos: [x,y], agent_dir: [int], goal_pos: [x,y], key_pos: [x,y], door_pos: [x,y], holding_key: true/false, door_locked: true/false, door_open: true/false] - #agent_dir: 0 - right, 1 - down, 2 - left, 3 - up - obs_pairs_root_path = os.path.join(self.dataset_root_path, "obs_pairs") if not os.path.exists(obs_pairs_root_path): os.makedirs(obs_pairs_root_path) self._set_data_generator_reset_type("custom") - for control_attr in self._get_data_generator_state_attr(): + for control_attr in tqdm(self._get_data_generator_state_attr(), desc="Running observation pairs"): control_attr_save_path = os.path.join(obs_pairs_root_path, control_attr) if not os.path.exists(control_attr_save_path): os.makedirs(control_attr_save_path) @@ -99,7 +99,7 @@ def sample_obs_pairs(self, num_pairs_per_control_attr): i=0 while i < num_pairs_per_control_attr: control_attr_sample = self._gen_rand_control_attr(control_attr) - self._set_data_generator_control_attr(control_attr, control_attr_sample) + self._set_data_generator_control_attr({control_attr:control_attr_sample}) try: obs0, info0 = self._get_reset_data_generator() except RecursionError as e: @@ -112,15 +112,43 @@ def sample_obs_pairs(self, num_pairs_per_control_attr): continue self._save_obs_pairs(obs0, obs1, info0['state_dict'], info1['state_dict'], control_attr_save_path, i) - print("info1",info0["state_dict"]) - print("info2",info1['state_dict']) - print(control_attr, control_attr_sample) i+=1 # triplet (o,o',o'',a',a'') def sample_obs_triplets(self, num_triplets): - pass + print(" Sampling observation triplets...") + obs_triplets_root_path = os.path.join(self.dataset_root_path, "obs_triplets") + if not os.path.exists(obs_triplets_root_path): + os.makedirs(obs_triplets_root_path) + + for i in tqdm(range(num_triplets),desc="Running observation triplets"): + obs_triplets_idx_path = os.path.join(obs_triplets_root_path, str(i)) + if not os.path.exists(obs_triplets_idx_path): + os.makedirs(obs_triplets_idx_path) + + self._set_data_generator_reset_type("custom") + self._set_data_generator_control_attr({}) + init_obs, init_info = self._get_reset_data_generator() + + # Assume do random policy + action = self._get_data_generator_random_action() + obs, _, _, _, info = self._get_step_data_generator(action) + + self._set_data_generator_reset_type("custom") + self._set_data_generator_control_attr(init_info["state_dict"]) + _, _ = self._get_reset_data_generator() + + action_prime = self._get_data_generator_random_action() + while action_prime == action: + action_prime = self._get_data_generator_random_action() + obs_prime, _, _, _, info_prime = self._get_step_data_generator(action_prime) + + self._save_obs_triplets(init_obs, obs, obs_prime, action, action_prime, obs_triplets_idx_path, + init_state_dict=init_info["state_dict"], + state_dict0=info["state_dict"], + state_dict1=info_prime["state_dict"] + ) def _set_data_generator_reset_type(self, reset_type): assert reset_type in ["custom", "random", "default"] @@ -129,8 +157,8 @@ def _set_data_generator_reset_type(self, reset_type): def _get_reset_data_generator(self): return self.data_generator.reset() - def _set_data_generator_control_attr(self, control_attr, control_attr_sample): - self.data_generator.controlled_factors = {control_attr: control_attr_sample} + def _set_data_generator_control_attr(self, control_attr_dict): + self.data_generator.controlled_factors = control_attr_dict def _get_step_data_generator(self, action): return self.data_generator.step(action) @@ -151,6 +179,10 @@ def _gen_rand_control_attr(self, control_attr): if attr_type == "coordinate_width" or attr_type == "coordinate_height": min_val = min_val + 1 max_val = max_val - 1 + elif attr_type == "boolean": + min_val = 0 + max_val = 2 + random_val = np.random.randint(min_val, max_val) sample_val.append(dtype(random_val)) @@ -227,6 +259,46 @@ def _save_obs_pairs(self, obs0, obs1, state_dict0, state_dict1, save_path, idx): state_dict_array = np.array(state_dict1) np.save(os.path.join(save_path,f"state_dict-{idx}-1.npy"), state_dict_array) + def _save_obs_triplets(self, init_obs, obs0, obs1, action0, action1, save_path, + init_state_dict=None, state_dict0=None, state_dict1=None): + observation_type = self.data_generator.observation_type + if observation_type == 'image': + image_path = os.path.join(save_path, "obs-image-init.png") + img = Image.fromarray(init_obs) + img.save(image_path) + image_path = os.path.join(save_path, f"obs-image-{action_list[int(action0)]}-0.png") + img = Image.fromarray(obs0) + img.save(image_path) + image_path = os.path.join(save_path, f"obs-image-{action_list[int(action1)]}-1.png") + img = Image.fromarray(obs1) + img.save(image_path) + elif observation_type == 'expert': + expert_path = os.path.join(save_path, "obs-expert-init.npy") + expert_array = np.array(init_obs) + np.save(expert_path, expert_array) + expert_path = os.path.join(save_path, f"obs-expert-{action_list[int(action0)]}-0.npy") + expert_array = np.array(obs0) + np.save(expert_path, expert_array) + expert_path = os.path.join(save_path, f"obs-expert-{action_list[int(action1)]}-1.npy") + expert_array = np.array(obs1) + np.save(expert_path, expert_array) + elif observation_type == 'factored': + raise NotImplementedError('ERROR: to be implemented after factored representation encoder') + else: + raise Exception('ERROR: observation type {} undefined'.format(observation_type)) + action_path = os.path.join(save_path, "action.npy") + action_array = np.array([action0, action1]) + np.save(action_path, action_array) + + if init_state_dict: + state_dict_array = np.array(init_state_dict) + np.save(os.path.join(save_path,f"state_dict-init.npy"), state_dict_array) + if state_dict0: + state_dict_array = np.array(state_dict0) + np.save(os.path.join(save_path,f"state_dict-0.npy"), state_dict_array) + if state_dict1: + state_dict_array = np.array(state_dict1) + np.save(os.path.join(save_path,f"state_dict-1.npy"), state_dict_array) if __name__ == '__main__': from data.data_generator import DataGenerator @@ -234,6 +306,6 @@ def _save_obs_pairs(self, obs0, obs1, state_dict0, state_dict1, save_path, idx): data_generator = DataGenerator(config_path='./configs/data_generator/config.yaml') mdg = GenerateDataset(data_generator, dataset_root_path='./temp_samples', episode_max_length=10) - #mdg.sample_episodes(num_episodes=5) - mdg.sample_obs_pairs(num_pairs_per_control_attr=5) - #mdg.sample_obs_triplets(num_triplets=5) \ No newline at end of file + mdg.sample_episodes(num_episodes=10) + mdg.sample_obs_pairs(num_pairs_per_control_attr=10) + mdg.sample_obs_triplets(num_triplets=10) \ No newline at end of file From 314648b6c0222e75c2af9b88a66563608aed3970 Mon Sep 17 00:00:00 2001 From: "chia_hong_hsu@brown.edu" Date: Thu, 24 Oct 2024 15:42:55 -0400 Subject: [PATCH 5/7] 10/24 push --- data/utils/controlled_reset.py | 47 +++++++++++++++++++++++----------- script_gen_data.py | 8 +++--- 2 files changed, 36 insertions(+), 19 deletions(-) diff --git a/data/utils/controlled_reset.py b/data/utils/controlled_reset.py index 7681443..d4438af 100644 --- a/data/utils/controlled_reset.py +++ b/data/utils/controlled_reset.py @@ -47,6 +47,7 @@ def _custom_reset_doorkey(self, env, width, height, controlled_factors): while (splitIdx, doorIdx) in used_locations or (splitIdx is None or doorIdx is None) or (goal_pos[0]==splitIdx): splitIdx = env.unwrapped._rand_int(2, width - 2) doorIdx = env.unwrapped._rand_int(1, height - 2) + used_locations.add([splitIdx, doorIdx]) # factor 3: control door locked / unlocked # factor 4: control door open/closed @@ -67,25 +68,41 @@ def _custom_reset_doorkey(self, env, width, height, controlled_factors): # factor 5: control key position # factor 6: control holding key # pdb.set_trace() - #if not (('door_locked' in controlled_factors and controlled_factors['door_locked'] is False) or ('holding_key' in controlled_factors and controlled_factors['holding_key'] is True)): - if 'holding_key' in controlled_factors and controlled_factors['holding_key'] == 1: - #need to set the agent property as holding key - env.unwrapped.carrying = Key("yellow") + #if not (('door_locked' in controlled_factors and controlled_factors['door_locked'] is False) or ('holding_key' in controlled_factors and controlled_factors['holding_key']==1)): + if 'key_pos' in controlled_factors: + holding_key = 0 + key_top = controlled_factors['key_pos'] + key_size = (1,1) + env.unwrapped.place_obj(obj=Key("yellow"), top= key_top, size= key_size,max_tries=10) else: - if 'key_pos' in controlled_factors: - key_top = controlled_factors['key_pos'] - key_size = (1,1) - env.unwrapped.place_obj(obj=Key("yellow"), top= key_top, size= key_size,max_tries=10) + if 'holding_key' in controlled_factors and controlled_factors['holding_key'] == 1: + #need to set the agent property as holding key + env.unwrapped.carrying = Key("yellow") else: - holding_key = np.random.randint(0,2) - if holding_key: - env.unwrapped.carrying = Key("yellow") + if 'holding_key' in controlled_factors and controlled_factors['holding_key'] == 0: + if 'key_pos' in controlled_factors: + key_top = controlled_factors['key_pos'] + key_size = (1,1) + env.unwrapped.place_obj(obj=Key("yellow"), top= key_top, size= key_size,max_tries=10) + else: + key_top = (0,0) + key_size = (splitIdx, height) + env.unwrapped.place_obj(obj=Key("yellow"), top= key_top, size= key_size,max_tries=10) else: - key_top = (0,0) - key_size = (splitIdx, height) - env.unwrapped.place_obj(obj=Key("yellow"), top= key_top, size= key_size,max_tries=10) + # randomly decide hold key or not + holding_key = np.random.randint(0,2) + if holding_key: + env.unwrapped.carrying = Key("yellow") + else: + if 'key_pos' in controlled_factors: + key_top = controlled_factors['key_pos'] + key_size = (1,1) + env.unwrapped.place_obj(obj=Key("yellow"), top= key_top, size= key_size,max_tries=10) + else: + key_top = (0,0) + key_size = (splitIdx, height) + env.unwrapped.place_obj(obj=Key("yellow"), top= key_top, size= key_size,max_tries=10) - # factor 7: control agent position agent_top = tuple(controlled_factors['agent_pos']) if 'agent_pos' in controlled_factors else (0,0) agent_size = (1,1) if 'agent_pos' in controlled_factors else (splitIdx, height) diff --git a/script_gen_data.py b/script_gen_data.py index 7302e90..1b99ed0 100644 --- a/script_gen_data.py +++ b/script_gen_data.py @@ -304,8 +304,8 @@ def _save_obs_triplets(self, init_obs, obs0, obs1, action0, action1, save_path, from data.data_generator import DataGenerator data_generator = DataGenerator(config_path='./configs/data_generator/config.yaml') - mdg = GenerateDataset(data_generator, dataset_root_path='./temp_samples', episode_max_length=10) + mdg = GenerateDataset(data_generator, dataset_root_path='./temp_samples_3', episode_max_length=10) - mdg.sample_episodes(num_episodes=10) - mdg.sample_obs_pairs(num_pairs_per_control_attr=10) - mdg.sample_obs_triplets(num_triplets=10) \ No newline at end of file + mdg.sample_episodes(num_episodes=30) + mdg.sample_obs_pairs(num_pairs_per_control_attr=30) + mdg.sample_obs_triplets(num_triplets=30) \ No newline at end of file From d15001a3990ef6d9c399dd85e869dd2bd297d308 Mon Sep 17 00:00:00 2001 From: "chia_hong_hsu@brown.edu" Date: Thu, 24 Oct 2024 16:11:21 -0400 Subject: [PATCH 6/7] 10/24 push --- data/utils/controlled_reset.py | 5 +++-- script_gen_data.py | 19 +++++++++++++------ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/data/utils/controlled_reset.py b/data/utils/controlled_reset.py index d4438af..02f4b2a 100644 --- a/data/utils/controlled_reset.py +++ b/data/utils/controlled_reset.py @@ -47,7 +47,6 @@ def _custom_reset_doorkey(self, env, width, height, controlled_factors): while (splitIdx, doorIdx) in used_locations or (splitIdx is None or doorIdx is None) or (goal_pos[0]==splitIdx): splitIdx = env.unwrapped._rand_int(2, width - 2) doorIdx = env.unwrapped._rand_int(1, height - 2) - used_locations.add([splitIdx, doorIdx]) # factor 3: control door locked / unlocked # factor 4: control door open/closed @@ -77,9 +76,11 @@ def _custom_reset_doorkey(self, env, width, height, controlled_factors): else: if 'holding_key' in controlled_factors and controlled_factors['holding_key'] == 1: #need to set the agent property as holding key + holding_key = 1 env.unwrapped.carrying = Key("yellow") else: if 'holding_key' in controlled_factors and controlled_factors['holding_key'] == 0: + holding_key = 0 if 'key_pos' in controlled_factors: key_top = controlled_factors['key_pos'] key_size = (1,1) @@ -107,7 +108,7 @@ def _custom_reset_doorkey(self, env, width, height, controlled_factors): agent_top = tuple(controlled_factors['agent_pos']) if 'agent_pos' in controlled_factors else (0,0) agent_size = (1,1) if 'agent_pos' in controlled_factors else (splitIdx, height) env.unwrapped.place_agent(top=agent_top, size=agent_size, max_tries=10) - + #factor 8: control agent direction if 'agent_dir' in controlled_factors: env.unwrapped.agent_dir = controlled_factors['agent_dir'] diff --git a/script_gen_data.py b/script_gen_data.py index 1b99ed0..631e640 100644 --- a/script_gen_data.py +++ b/script_gen_data.py @@ -4,6 +4,7 @@ from tqdm import tqdm import numpy as np +import copy action_list = ["left","right","forward","pickup","drop","activate","done"] @@ -130,19 +131,22 @@ def sample_obs_triplets(self, num_triplets): self._set_data_generator_reset_type("custom") self._set_data_generator_control_attr({}) init_obs, init_info = self._get_reset_data_generator() + temp_data_generator = self._get_copy_data_generator() # Assume do random policy action = self._get_data_generator_random_action() obs, _, _, _, info = self._get_step_data_generator(action) - self._set_data_generator_reset_type("custom") - self._set_data_generator_control_attr(init_info["state_dict"]) - _, _ = self._get_reset_data_generator() + #self._set_data_generator_reset_type("custom") + #self._set_data_generator_control_attr(init_info["state_dict"]) + #init_obs1, _ = self._get_reset_data_generator() - action_prime = self._get_data_generator_random_action() + # action_prime = self._get_data_generator_random_action() + action_prime = temp_data_generator.action_space.sample() while action_prime == action: - action_prime = self._get_data_generator_random_action() - obs_prime, _, _, _, info_prime = self._get_step_data_generator(action_prime) + # action_prime = self._get_data_generator_random_action() + action_prime = temp_data_generator.action_space.sample() + obs_prime, _, _, _, info_prime = temp_data_generator.step(action_prime) self._save_obs_triplets(init_obs, obs, obs_prime, action, action_prime, obs_triplets_idx_path, init_state_dict=init_info["state_dict"], @@ -157,6 +161,9 @@ def _set_data_generator_reset_type(self, reset_type): def _get_reset_data_generator(self): return self.data_generator.reset() + def _get_copy_data_generator(self): + return copy.deepcopy(self.data_generator) + def _set_data_generator_control_attr(self, control_attr_dict): self.data_generator.controlled_factors = control_attr_dict From 097977547f532cefd98e267753b14d1af640ebcd Mon Sep 17 00:00:00 2001 From: "chia_hong_hsu@brown.edu" Date: Tue, 29 Oct 2024 16:56:48 -0400 Subject: [PATCH 7/7] done --- script_gen_data.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/script_gen_data.py b/script_gen_data.py index 631e640..6fd3c80 100644 --- a/script_gen_data.py +++ b/script_gen_data.py @@ -154,6 +154,8 @@ def sample_obs_triplets(self, num_triplets): state_dict1=info_prime["state_dict"] ) + + def _set_data_generator_reset_type(self, reset_type): assert reset_type in ["custom", "random", "default"] self.data_generator.reset_type = reset_type