From fbf67aa9b61ec87ec237c16c79b5f5afa4a6cdd6 Mon Sep 17 00:00:00 2001 From: chiller Date: Wed, 15 Jan 2014 11:50:22 +0100 Subject: [PATCH] updatet framework and implemented push-relabel algorithm --- .classpath | 2 +- .gitignore | 1 + libs/vigral_plugins_framework.jar | Bin 13814 -> 0 bytes libs/vigral_plugins_framework_v0.2.1.jar | Bin 0 -> 14235 bytes libs/vigral_plugins_framework_v0.2.jar | Bin 0 -> 14186 bytes src/BlaAlgorithm.java | 6 +- src/DepthFirstSearch.java | 14 +- src/Dijkstra.java | 4 - src/PushRelabel.java | 421 +++++++++++++++++++++++ 9 files changed, 441 insertions(+), 7 deletions(-) delete mode 100644 libs/vigral_plugins_framework.jar create mode 100644 libs/vigral_plugins_framework_v0.2.1.jar create mode 100644 libs/vigral_plugins_framework_v0.2.jar create mode 100644 src/PushRelabel.java diff --git a/.classpath b/.classpath index 64c13b7..1eace23 100644 --- a/.classpath +++ b/.classpath @@ -4,6 +4,6 @@ - + diff --git a/.gitignore b/.gitignore index 0be1402..ca47ac8 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ # Package Files # *.war *.ear +/bin diff --git a/libs/vigral_plugins_framework.jar b/libs/vigral_plugins_framework.jar deleted file mode 100644 index b75c6428ad499a08360f61281ee755fe353d4e2c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13814 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 F{eR#`kTw7S diff --git a/libs/vigral_plugins_framework_v0.2.1.jar b/libs/vigral_plugins_framework_v0.2.1.jar new file mode 100644 index 0000000000000000000000000000000000000000..702bbb2566cdecde8b046e8ba17abaf6d9897198 GIT binary patch literal 14235 zcmb7rWmsI>k~R?B-66QUySsaEcWvBBaCdii5AF^Df)m``-Ss1LXXfPIxpU_Es-NDy z`_J2}*RHDdmMKVo0!0OagoFfwRi_dG`a@8GK!IdMRRn1z<;3V^1?42gM3q(OWX0Y_ zfPk)Le~!vX)6z}BNz+n||D32(Vwh##*xlL%0aB2Lfc*Xy%^Euo#zWLM(`Jl2j?*NZK*wgX5Vd$6015kMTOeE%QQseC@OQ)UAN0$WHm{CUmW;y;INL-7cZKImm=d3@|m3T3al49eRJU zS5%BTa=oIe-I8v4Y$=}mrtTK)H%ALYGO<)%!d2}zXa3q}w(7kRDlwAauvOa!v#mnT zj-TLmiKUrJ%M#t6f?D0zhs0u@xxU{+$4coz9L8~(+HR!844Qe*CmT>m?mAX)9Gc8h zD|--@pMWN>roLZ*4FqKxgcWw1{;AQpD;rD9SksS~;i4u23QLPE1Sx(vTb2tKDZ*7s zv}@891epgLX)%iKSm-6z9L^I@TuN&(w9`U*rg^pKI;gFPnpMkmnqV#8oG_r(5T*z^ zIiiqVSng0t9P0Z{+nCjCqPD0I6xGj2ia;Z|%Zq)Ks~8TW5_1TBrZ}C25?>_L+&_7H zpF{D)NRXarEI}G!`Vq5+1{1%Y66_SWb6``Ks?+Xif<77KTV|%!=RtUfHw;3vJ@Drp<=?q0(#QJ={Z+C&#l_VuW9b^kQ zU^DQ3lZRH8)F=mCka2As&*?dGocGZ{;sAIZzUD8hKs~bk*=h#sY6ra0Fnoq#Jkwv2 zaaROg8#Y`Mb~}0p5b|C!uACGP^&RNFsT`9DqYA4V6ccIb+t ziu&F`Cz&oMttEvv(z#%)1nE~X@SWw`6wtuj2pN}bkc&PSWxOOX24DbB8xd(B8XqG{ zd?Gf1SR5hyHTY%k^4_#aGL4M(Gt>E4dfUrcN0+DG+vE8}7qIoGiz zD_%N_n9W$kB_ks`&YX>S7p6#N_mU+O#I9pkY4mXtiikkYb_HAMfXoTtW*iyXcl;99s#gwiu`uXvi(-I&ef^?E2>t_Lr-Fr%Lt`5L3 z-@}xLEryZCOgY2SS0~7X!}|s$3KnMe)@<4X@f1Xw+Oi_j%pm|x2!{)`UO!gAn*%=@ zHduiEYRBHU3Xm7Ze`qK;U31gda*4ExecccLb=d;h`XXO>wfW&O z)qrQUktPRsK)Y;O_>#G+12wyG&1nQe8nEAi*NW>aiUNZ@Ps*=TG8-N4N^&zfsL6A7 zOrQIJL6D@(Sulvcg-RO!d>Xnz$;xz*4EC5IZ>TggTQtw~p3OmPk{e`3?FGt0*rGri z@utA+N3^KQp0F@&gbn&Eu>)$sbYNcU7+epP>?7DN!Iiwcl+66I-j;oXBi|@8$X-c} zjnI{zk|Q$tP$E5Lk~Yc8f`c*LyfaX@G?$WtMtMFiUBW6#w_+*o0(X^|EX0}XtfR3~ zCyr56Zd|VFrdE4yQ2~Iyzo1w##h5H^|7fF4)JQV2lUF_M! z4#^T%oImIj&}XpAP1re)Yt^2i2V<_}HN`|kcXpPdm1CjLBRta*4#6R0T6>OQ*&{4r zGKrl4(XKe9c@D!ex!cF$907BN_&Vh$U}3T89q$E#F{Jk#MoSC1@xA1kXg0$5#Iq5d z>&*jV-oyZtLzk{nle)ORF=i<-2hZU_DsbIVJ>DY);%ZdgXVxnpz&zR4UD}?8Om1EN z1l!%^nGbj63uZa?sUFYHBDJ@d(&_Dtie`_wAI)jf@0WUS=2mDvjI<7xZf<8O?7C$O zopSNRaceMIS=vyUr+V?-ig42seoL_V)CDr=gGwleQ~_^$-h4g^j=4+zv3a4{PgfGx zWABPlieEC+xMCrX<9MCYIlPum&^W)$@zY6xs+LKBs<^KYJVREIq1Lz1YOIak8fUKH zX?o>!hdM+WM+c@47wPm5dj!uUMBSSnAq~&C6{_ESox9LvAXfU^B+rh#nL#E9HmUC) zFFsi&07mPw3&wMi34B3ffU-n?ID6#~#h7!(W=o9Q`JASr6l==>$Xl3_yrL2}=R_|aG>wK0!*6JD9nLV zhMM5{&P?zAQ%_sPXFP*f46D_?SVO6Y+lGj`)vE>BT3+u#-ahG>_q5?Y#U%Wn_!>PN zX2g;Xuot&EKkvdV#ekiA0tuSM50_}R9rDrD?4EDKExx$7qo^LU)u!&KD<41Jdb1K_ z;{t;790(HiHRXst@dG+vemp*)@V?6=y$ET$Y9#7O?+=in8^ur?p((*98NIW!wG+oBi4&Sh04v=$Kpizn(cjUa;V6{SG~Za<8P1CzoBCHQe5+Z)&54ou@pZ)>7f2ozbG4K+A4czHaC zF{~;fA}tPtE$$Ba%VjPXi>(s*A4*jlsI&I54J=Aa$t|BuF!Qeoe^*necCAy8j!E%^ zJ~PTBoZE_;H&vz8uATzv%GF0fz(R-QpSoeG1zn>1$*+Vc8bLUlCk68gM3E29xW!5Y zcaCR+58D6KdBWLAuF@9qibQ7mq%43S?}$j=`Hm&Yi{ZK}eV$Qr2kzqE#X3-4FzDGr zD3qM$xoeX>`Wq`^)CA@)^j7*UO~ z2nw2nvIsJxNC(_1K~YR#2av8N=rKghOKco6XOdk1@X0k)p#mZ32Sn%>$|@uccxe%m zkS}8T(ds8EOH=$rx{K7gZDs^{-r{fJ@|11Ek&NC*dV0WV5PTOm!lhbMq9+DbR@959?>^9i9_9|Tg4U@<%;ngg?2Qug2fBj6F4bu04$0Rn0S z`%|lJzx;DVMf`th^*_|P;mf0|@(|kFVA2iABk-U;x8abrE(v!=DqUpopXm00%PT7Ol}{t{cI0@6Z8Y z6#sEnAH|$as5D81VFekUOjAs0icmU_9-nDTtmG>TqC6&VsRUES9vJTFra8wVp@Qx@ z1A+cB5)77YLSJDYd~kRB8DRE67LVVs9|1H<1lG6gOq~G{3$nlOs)^M?8a@~WWVFr9 zsa7_psxv^M?^}?R?<28qt$;KYR#g2797&KTNWSe)|4}$!FfQ~w%^brY67ZOp#vJC8 zH?+5KtID1({U!V#;~_mNPX{`Wm$xCIo|$>_;_XL|tn7s`dpk212Bp zCG%6?#DKpLpfX{AmK|T8vg0N#b#Qr^qt~GDe3d9%Js+%G$T9E+cWxN{EQ>7+{%JWx z7Gz1CAdcxNO3LYF#=owA$=Idw-~p&nY2Q4Iz?ybL7`XbXm}Ih&YiUxht2|af4VdVFXP%P1082-p<;P}m^DW9>KbzaXcFMkm0?_J~De2p&bdXRno%%~U;%w4h!gLu=?gVxy zGy}A%ah%D!*+L7ri|jf^%V)2N}S&mmB-Nd-64V=Q2|cWyikYj|=bq3PxPJg9Ia%Jxt0Td%d# ze2#F=7vG*)s2jWG*vC`I@B6s$d-BObZwqCtL9xT*EzUIPe7$9cIC*R-CE;=Gzn2Mo zIh^^Kph|_KS1S`oukRW=3#H^|VodP;ymYo&5-oey0Q=7Fb~+~pq*aGOcj)y_ z`OnO9=fIWAxG1}A?sf@qF>$z5D81ZDcjct(k%Rk!u=D*Bnjy0KVh8&#h*Hb^+h*xd(3Kdoi4?3%Eu)2r7aY~+=W@4}D&tNFf zNZurK`2^~ru%Uh36Is;O6YxS`b*EmNz0`V%()jY^R)tEb($#*XJ#*=)U3@OJz|)Hy zDAP58f$Q8nSj?wFJ%7C$aG=Y69JgRgrqoq>#9d?r78KQ|Khf_ORA9s9C%#o!%og&-|gR!B)X)FIF9~a4$RjguKtFZXQ?I zs@9`r5~iw7cOKprPN|;L3$lfkE}RYLMU+D(HxE26(ZrE&YGe6@j1Q>jtRAy9(tLM1 z{hKU&TyFRcoHK-+na(>EpaVq$heD*;)Q?tZzUqDNR#Se?3w|CaTh)9l2AH}TTkIR0 zRXlxJ9>B+!(2AXd4LA!G-R&@RP$^(VxN!FUFPpSy2q;giFKc)`jHVS}tRVp7{Sif6 z@dU@>$>@|cZgCLY-5-KlIG2o7mLXb)Obw(Zw8N>dHS$c!E^tDxWBEHuIkhfvXB>5P z*j${|xpJ@0Ao1!kO`#*oiy*C1pT5^TVKZ}{b4CZQ$qcro(;3o4Mtjn7ysxGVA3N2` zNuQu-Fot@x2zjS6%>-%IJFbYeb3eSZ5v>VgAE|^?G3eAFR_?-w;&+*H#-%_7_JAyq zQ7TkX&SOcKIFkk=YzPisNUA<(D-GHLb~f4^LCn-A5N_GNV^5_0GUty*!}lCKS4$rn zY?yG<3s~N-ExcS5Y$-8x8*(Mo;tEgTLw$Lzxz%)6*^H0 zv~zHcn`pnU<^`;0oKw!A2WB!_w50uvJRdirwn)MVC`m{SFDqbipMkL^!k^yTkg>SODAc3>Y!`6kA75>ea7JEsw~ELSjI1ceBJwa=KTg}qLHN& zVR^W44}?Aikb6TCT58z^5wcPy$A!tX2cxsn(aGNJ51b1f7+&a6@5mV62Nd!F&`j-! zNqzdv;1=F)nn-SSm>%{}$rcSs+~TM~$eC23FC|;!#Zshmsn!nP$fbx&c9jG3fX+Y3QR-VfW)QEkZGqSg{+eT}*oGWG5 zDy|;o>WI**=W35bo`-wdk)Em&p0X`6t!6iI&F*w>YTRV_*`H932 zVoFAatDlxJKZt2>+WnvPqF$d#U1@Z|#H zMR9kV_a&5gQI;K*FnMakS@g$leM5rhdJg&6&&!ZJZGXNlJy}y7&Is+V!}5)AQr;G1xa}>k&u>8eE447h_Fy z*IAUhGt49@>0^msG;14;T4#;T5d?idYV8e6k__fm$Ie(Vd(lp9G(3lDR4~60k0Q?M zwohY84f6yp|@53#1lrJx+1qO_x{AQ}NUigxrKQ20o*R0Skd-$R{8YQ2Evd zod+4d$_vH_8{6P#acx*^-<|p0Uf(`QBv*sEB5X4S#B&&vBqEmM{)csZ7E0d{V2LEY zv?pRPMnqFAjBw2?XW7MFxCdGdD=%mpb5*nMmx;vvG7TQ?bz1t^ddx^TOgt}RVKnT7 zU32E_w<{7JwF^kBph%x2ol*0qI`*lzXOk%sBagc6*#~K5ZG-k`Z`p)6!PSc8pk@1m zeY5!`$4{jzBerJd0OVH`p=D*m6(G^YXe53y(FpnQLnV`#E9jt7yMRgZ-Yv?npUTO^ z3Yq)m8P9w}b0Elg8PKk}>mf}0@KfTuP~to==gWKW$!;x6f-O3*&kW@F2VO9?;5PUw z8N+gBvZv2{lhNqCM>@k`-4W?_ZbnY9(5tZfRDil9FYlPp1M!#|0!+HR<151NLh<*? zs|#;LS;-SlC7Ji#nx7uAaoQ3P3xTU2aV44nQ;apP@%EAG&HvhArF6@qdMxgw|mj)bU4ENuXo zlr=7KZNB6-jFK20>8e<3RKUbW^3)|rUhKmXf(cKPg+8LpT*3Xyddq#rGyi@4N8H^E zQWL=n#S6=wnk%4Hd3%P3U6sny7f|Ud5J!u@s8g@bc`lp1UA3vrEt|@ zNV8gPX*rbjoY!iaB)DT8he z)dsXvt9tJyBDJ8S4|)p`C59t{Du#oELxw^EAmQLvMldY6ccJYI8#`f&dLv|TK;PuTk5pSR>dYagIyfYb47^Cl!}=-w?BM&Do_|Z!w72dJfoVauB zcrZztn2g2AQN5=VVgqRve0qhEad~b1Gctt&xDdYt03G2Nb%8OKasEY<6E%-lbEL&_ zeoV*rEA90t2A|N!Ks(p(wN_A)To29(#M1bkRK@Cd$fI37Z=dId$*(T))P$ekKL7U2 ztlQ-iVILa4{!bciV@>u?B~7}&^UTI(CM2RCmw&1@cBtt%qNrl}$i=gLw$?IFC%Q7I z6`f`yMFr8+RFn|-0wW4NfUY3N7VJd07}=IS{RHfz<54;P_6f`eFZB}Qf&NC$Y!>G{ z!`^FRkrd7%ea@bN+4F9vecyX+|CP(^>&x@=XCT~xVx)Qo5*Q+zpXr5hfN2=hsm($b zxWvbsR3Sy!ADcAnJj)tk1V3wD(e*YCk(q*#f=*Fq+Iu72d%usGEIS;^ z#sry7d)=sWb?b*5w4BWDUMFLwj3ZJXCmq|5BEkyCYnd>OBaR$%1|0+_GSSX(OTrBI zUir>qm#OosLkXcz_jGf!-VzS(j*yo&Gyf@)f6!tLI;Km zY9twHeWg1aUG|)o3yGvH{Q&kw6?-q?!w3LRZF6ZmXZ0l{IOZM8GO{>-)(ikqGDz*v zNzglRah0uEI^#>E=_7UFE6O$_=Wd5EEA>3P5^BQmX69YXHC^0` z&8zGeVL@MV=W$YY+yxs}uYY{wf+*r0st+6KKgK4ruUZqyiIu2Qjp^v6zPIRjH5%SJ;u%&JmXjckKPzG8Ul=0O#|l>BKX5&g6+}Ud=vL3Q;68uGs=)# zc98@~_wmSp%l3d;;cS%bwbG{hUwK|jvIpzkC1}n&zBsv5$IAwx$6u|RatN_{tdo(` zP+mkvPgj0ls|SDD9Oh8PiYR#F2Mrxl)Yv_IDpkA5Xun8eu@+8P^0j4Zl?`a;{%mLX z&h$CC;m$V*dM$UxX{m}Uh{I|`DNOQ0*nxkncr0(AqfGdCe$G(F_SQ&0uZ5hPk~_^- zqjxx|`53y@zUkL$$b!7K@J;}fZRFyA$O`SxrDPl*AxwUwVok78K2->To@_Kdd&^9aBnP^P- zO8s@JKDLI3eXbKjH*jy?t8Z~Yo6iT2WrFwBt=~?D>U;+=SQ@82PY9pPf|KpPWeIwS z9dKsEZ7X_YnNef%BdwtoJr0{>sKwWfy4iej`z3=Bh)@y9M@xihpx8QLG-5o+uHg6; zcAv43B61UCO(9_r5Nk^4Kp;q%MMM%L-HaRal95Nu$kdlhyl$}P=0<^}+rui!iG&Y7 zv!vBmX=xo#Jhetg4rb_Wm8e(Uug^Ox2IW+vdsCY!G2@wNR5Zxw&qOo8sJxv5#UU2! zC!4<`;f)TE0du!9fb%u;Jc^q`R*y-O%W=;P3nU5-xCt(^R7;!%Skh0q;`G2%)e!3C zim~TPFtN5_PRdS_|MEMk=5E;Hl0$Bx<`Qw~9557ys6i#NE{L+N7rS5Of<@Q&@*il> z>4!%dJkX3dE&j244-)aIfkG7!60hqWyj;ny>T^}#M1^(aeI=LHY zU-=_f3Jv!sA^BH#P4s`b>whrlj*oOH&KI<|ELy8;5*J+V1}otimV#-H(6rV;Bsm%D zQAsjqWNdD^?KBe_*&WG-=KR`pAd_Pu-=s>I`rH#*Zb@kq#~;3ZoG;+PuNNp^LEnLc zJ=Y_|r;UyGaiRIm*Szi4I_{s(uGS9j-`{@O0l{vbLTZA7JBU%W8KXl7C2F!>C+SK| z8M#xkCXV7D1%TeME!+ELD}&{mC!9d`f~+Rrs`9E%NAhPbmI%H zqI)j#?4LNz)En&s?}EaV3o`^f70ZofMt>}UkM;9laT+Gcc*^Kg<=U8-mfv3wb6&A% zjAJq0Y>h)cv4v*iaOLUaK!3D#AaZ{-l}n#8EvDdkPU9;7f*UEkvHD?`$pVzQCQPaC zY5k|1re%0Dro$X{O4=+H8sv*QGrJYKDKoV3`)7tfbeX6@>skz`*hUn?B{?n1IXG=t zIrOG7k}KlRVYvtKd{!#^?hL)58ZoTUFvY3i0on-22_g=3V)mW#f}n~?XI~J7GYTP4 z>$#^r(I}#v)CD29G(58X@S>bV1TkE`vlMN-W>{-#Ub5NpB?hK`_d8UIkU|l88pmPf&1#BPftgKZ(^%x53NRl*3$>Jhx8kjmNZe;CQudKpHi=)!i@CUvq`po=simSR2TF8+>7F{>;H(g#{172?@?b(!dYrhZL$8&QI;=nsZNn|lz zldkG+8q=?=$ui*GbhsEhvKXlpg{e_t%^3?;t3*hF+Ch=9%`A>aZ+pzqX?gwlH3nd3 zv?|oY$ur+!4WACRU>OO8h z<|Y;3%?I;_4%GVVO~kH*eFft*{I=i!6`%B!@$f#wc=h!0^zOxl`0(s3NJ>dU%AX{# zu)hRXM+_|(zP1w?|In1DeUUML138Q?v zD$5Nm-%`&LP5f7tk*dsW&gX=iL8u>~E$IbL#y_S|&-(2>zWV8B^!u1Me=Y{3bke7+ z`GF?g9Tf6DANhVl@~#b5JQXse@wE({x0peNpS}OUGW#uOHG29K!M$Qy~kUDT_UNf zE0d+M2k?dK4V(}u;uiopF+1q8bt0SV@b%^XEc|>alC1)9yJX~hI9Jvu{0ZQMQWLNw z$)ci_K}`JXC4po!J_ZMrxdA#)yz(9DhM;mC`HIc>6IZxw!qQ_(vox3DiAf{4i6@J- zihRzkse-TUz>HFlIQy=?j8C|H=Tz_EYN^W&<3Fk|0}p%D2HT_db^1ZgOc_+Pxa))H zM;aQJmL>-^n;Y5MYtc(9k&dgaQzGV)W}HVeoyo-JFH~F9!-x3XrQUo?USpN6$+@cE zWyo*!N;Kc3EZ%Xlde<+Z-xQO-ThZ+@pq)yq)Zp?4o)oVfzTL}BZu(E7Z=XDwgFS?xc&H6~!=hpy3+~85H zm~MTnfRHNM&S+N_O!Xmzmm_iP*{?fg(8+R|c zY=0m^S?UN@;yfe#W&kREXQtmFfPmmo|6~CFno6Vow+z6*+RV|FJBHRa=5UjyC%(L_hZ%;1&e%c7_xy=rk#G^eY_$zei?zE`7$X~dc>Hl%At z?;JhHFLtoToYl4vyCPMh;5|%_5v*ISMbR-%*y9zctx+{^g$;{x@HQYyfc5kGRrtCr zn}-P<=$_6pM)o2`-n33{`rWEpmJ2-b+@<<}xY%IMqCC^8{jtALg`y{D;cZM#BY+gt!i5?W&r-$1kc=&U(k*sgMmYg=ve*bJ){ifB zWLgz6bD`7dn2^!X^Xh14`@^tOa)_JicZp=Otgrh#NoPzsBmz8lCE+gm$qPhOB-#N= zBPLtWC&DW>swIV&T$h4D2+Upyo8Y)JX+4t27C!%xLh=m4#rpyb1a$uqWdGIDi|{Wk zy@dbvc{w{-Sko&QSUCJ=%2P=v`ggm=r@~3iRUMj=jjFcR&$MZ${-I=25)q;Dk=QPM z{&sQj7iM?{Q?dGF}%D5BU+UrZpgB>HDPj8>PjUG%;G1JU= zFf+nA_9Ow6L6WEtGb;T(%Mv6en6T*>QzoeWQ|6fMhk6%+Bi)8Umdz3TW;JsC0Mx>n z0A^HqVIg&*aynI0tq74N1CFb!S)Q$XiE&~$qR}NcPQGonumvXooL0fnBQFdrJ6?kR zNZDSu-*6357}8f>@Ads*i`nQFZ5N)9E!_mj#R&moUJR6=Q-CZ;y{mWZ^JU-Xw;nD- zExR>BV51*1F+I00sNn2>tIW_I$n^mylF6NGnV7leD} zMF^?8Oz3PU6|b-Hb!Z+kD*_htw<<{~oYEDwfcc+iRFl+>NtMyy`PcV^!5Fc{2LAhmAN72C?sztvy8I( zQ)g^LbEzYz3*-AOUT8D>}y!7ZWB3OO0uGV1-$*3C&fal0=YG zFlM8eWSNg`IK7s^2G)cc!K7_INf^pTXSMLTS2d{am~)Dr+6GX!?yJb?cRalb-j^ux za-%QzODhj2ZYUsV;)3%w+>D7umoIjT*3u?Pa1`2es%E5d`7}J%JU=#Xq>Auat7xE`|67BLpR=rJdAMy^uvJ#zcbm^in4wWi@Zh1y8fH@5FI;l)w7srS@yFzN-8 zR5<+5X5W&vi#hn`DimUOr~<07a;9neSyzO&R5p29ZGFG6RBQncVDAQc4g2gFuPMbC zAMoNaePR3=QDaQsHC5vq+#dv4!RRFFr9vgq;R?|rsbakq8)V}po%6g>5t2v_+vk&6 zxnE%jw?4`!70`{9rlP7jjm?ykR)3)+iE1u4__8yX%EKu)T@i!}%Vp~_waQaDJSs$r zAunyb*{DeKqwj1Rx#oHnj#Z;V-J;g~$J^a(=BYgvCTBB|o^T_Z zCc9w1U8{vT9udx}(hZNa-hC!V4!27P-~>{qRQLurhkefJn`3pxB+L!0G6x_v%O90T z1n=`8x$)GB{>`Sc$BesRSMmdSy#fsb5)Nm#zzI97ihZhXhpNcVF(h#*F>KM!IN@OL z6JeFA{q-j0#&rTXCb7vjXi+}OmqT|rcKcPr$!$M3(4C{C{1^k|CW{GG{#}KoqQrt_ z@s$0n{M3#JFi4s2u}M@#dPX~>oS>F0>v;}xN|biWmqnH=_wF&SxL?Vte=c%~Y^u6S z?7d^*)uMLzV}W>YcC(9Q5%0K{-GGE@R|w*l3Bu=L(aqnaLbf4{4LCEN zb#%#vv-{}oGN=UrNAJlKz~i( z{5d-FdjjX5<$s&U`4i>02mQ1A|M!^9Ut;ia`~N?5^RM`Sc5#yY1^#ij^D%Sq_xS%H z0so5lX9wNyLeyX4^|4F;8{+@$1^pBEcmLg=CEMTqcYle}NABrwasT~7|E#6`uJryT zoF7%;{|)ee)P4V4=kF)>X944%|NrI36xII$`$t*sPu$=6v_CU#zsnzg$qeq_;QrfU z$iHI$$>D$J>i!bHkFWphnm@4r{nq};F@H1vza-#eOa3R`A1vUXH$5`+EHW}Eka%wx^h;#{CWL5lip1|kEf_KZF$@!9Ow;5?`}Yt-!btQy zhtM`WM?Mke*+E~u>@vDlEr2IUPI;=wwJj<O5^uU~$(?&8?dI<{LUT;11&#AKYlzS~2?OzcD$#CDq8t|Q0rpMJ|B>6J}rKUS^lpGa3O zz891kha#<@yjy_r17+xg5p_JF%QWgS*p~ez`6g`|N&VmgS;wU26 zHEQ;U%!Uaw8%A@;^AKqW;ff(FqBiT_X(T>Vzgl$e)09I=uVOfjwUlXy?bWCamIIv_ zlFi5~u`ePF@_M7LOK&hzUX=9@@1ZA#rxM@g#yZN93xQUQJcK%vn@UHH$rotonfQ5^ zN%lzpIVH|ej5yT5F*R0Pnm^|Y{rro+Tr-mY&73MF3@kJr>-_nJ_xiG}KOO+gKt!3f zI15-$9nYNYi|7Diy}aFQNm8^!+QdW%kN<(Ug1r>Ig?Q8B2h?sPelBR`xjpT{yp*Q^ zwW+tJl^9Y~ZefQRm}Rsx$8hwJY%#xAdK1T(Eg(+|L?Oj;lGakWMn6M~9mzPWix<6~ z39(73qquUfXD0Bvi57^umJkJvKwgFK(-fNECy1ATR5@*gnjG)%w|?0Qz{8K zEBwy28_u!2tzEtF+0Ut0j&g^(_Ou@58Yt9^y>}DsEkS#`8z0OC?6FrZ(SyvnKT((m zJ+;92U|cPtc^FkmXS;ce73jx6eF!ENLAw{*ei6!f*34p1R>tf$!lHd4r$DjD%+Wr( zQG$ve>=u`(^ocs!YDf4v4;8ifW1tEOZqLEeU?(u>8)5i)0DH2v!g8Nyc-vJ^#?@W;B|1`mW8eN$3p);}) z%3CXqc#1SYLjrZEZNX3;(z~?x2h;aSpx(J55)LVUCtVKm7;#{9+g@Bv1jOD5JoIqU z@u*lrQTU9Pfakr-JL7!uWD@F64CkXM&Ch48?e03S59j0Uz?OY?{4Vp^z>-hb5^457(!_sOXds^yAJI|5y$b!LVTIqr7T6glA~B*KTY~bnKZEJ zzj!TO3Tg5Yfr4y{TM4m(EyV~=^7pfpPHKChogc3`F4=~L5>K$DkK{7hyd@T7Y1!)M zxEXV?MAB24D5RQuY55zmdEOw0!$8mcG?{WkI0XSvnwN%|*!!XiU~{0<=tl8*vf)L* z1n|*b?bvyh+hzyz9_sT?Ro-+rULvmIT?tqw@Qvz?vg|Z}Q{4~6RP%}(Y>ZjK7NCv? z^h0BP)XVe!j75|<3pJ-(#&=zKMl>b)!>(__DxV!EDUGM-(brqVcZa5wkKf^gBJjW+ z9+(v5#~BPWFYxNfS?0}$j=`3hE%A>wF?_jA9^}|=t(H7_y3lnD?bblnUPxCS&EB{S zmEh^k#0dedP)?g>UL>xnKn*S&b83E&daSqLRie6b!oXlp6Ef@Mj0T6h;+zcj$};S& zQ|Dj7Aczv@%;Q)6<;91Kg%bYs*Yb7ERMUXEIUirTZ9Bx`5K*x5!Y3 zJjpP65X{Om#?6fDVEjLc?SPsw9GDh41k`*?_{!fR#*whRl)yMrW6iq3mSYg+Zzr$J zg6~XA&K8z%D3+2qK^<>l#zvoF+UBQSlts=)r7$0zB4!b;UAh!~fwM|T68MGVthKI8 zE1F(ddQ7_frb=^eQPvi1e?hKvl0HGy?!iivppIzbUX#z+K%n!%%u@s}ab_fSOp&H^ zBNk?7XXps;4Xnj~Y+zdZUr>BIUuB|TH&v*AAr>Sg%xkVbJq0L3vPrG!)s0FhJ z_4Z7Ne;nS7>nG1Ur>z=9%EJDv-lM-ksL>CMfg$MzDYBUtcb;?9P& zt~U<|x#N6|4xQSIjH;u%M;RqV?A-_ZD8RLcb-0gY2`f;vpO~+{+Rl@F+okTTP2<$& zjkVrgo_=>%USQ^a`$Q{c<`s@V~36w58@WmsOAkvgQGAo!bo$^92Bt_-3sx}S$pm;L7l0Jbd zT~sN~Fcma;laxx(Zse!oO#v!VPqs9MqSGj@@D&lC6kTy@OwBTj=3e4q_G|`mq7qQO z0-HB573G>sTd7WujAdrN{tqypYyW2)8 zD-=I+N{tOxJ|q+hd~6=}(kxRIczr0&Y}v9-x~dHx;uyOhs&}Edgav);;$u*!L}v7x z)K>@3`NHt#Gx@kxaK_blMYmevh1s8UxUG+%U9p;*q2cl7@A)+)?T$L+YXK4O2c9}N z`)QH*1FXeu_D{R8OOasb?m+w|F@uHb&4)ZRmAmKLu#3;GEyzm8ELBN6stU&sKRua0 zXW-ZdWZQp^(^Z!y_`qx1_B`-#kIelh8UHMx>8uu~1K5+x2my~>IU4_NH6!(O9mpCH zVH+_H?#IYZC3waW<%0jvNW!lro{JJy$o3{`sXP$SRRWK;HkHCH%p@+30`$IFgOk$)ZN_ugkH17 z*pZ&4#~F*P7|FiGSaE-Xktkp~;B1vHGWlt_Roal-M=HuoKTlJ~qj<#Z3Zh3v(Ev;g=O63MhGb`0iPJlU1K3taDdo#IH|ejnuk~=d z7ol5~M?hTc4PM;s_mNIpE)ZEI@Hv#I&{JjZX6ao7NJuZAj5G4C3I0%)t#GcE1wV_&l@XIYgSBxv}fre!(*aB@=o3`Re>(ijPS}M2#4a&WJ^H50FmW@({C{o zz@Fn;;eqx%ww+L?Pxa{JsH zsf7T?hP0A`pZtmN5}l$ij>?%hYJ$Nh*yLKo3kZEpA#!UnR42LwiE3@c;G^9E=4*jl#L9{A?bxO$^SkvEauXT`&KV`t+<$Nmk}ZYzAAkr_AumT%g98W= z1*(YXMyQ@BE=}?hXfIM`HJg0S_7r^$ks)s$45Rl%)X@P>hTyrl8C16uknI{p`&i9P zB6RCFa6`R^wswWxu+JiXW*WkY#F&pOn)*io74O?>E1QJh8Wv& z__)Z*)w@8UV{jb!qPb`T*B;$5DhD5`>7Fm~2nO9(Lx9|4chj7#xX5FnsB zu)ou4!v9OF|EbQkDi6*YqNuNZ@i#;d#CE9*l38H!*_lI9XMnC5 zF|QQ*0s?U1yo9qf(}g>2&Se~ zgi|vWS?ao%wk}jB2a!MdZ>trt;Ghg zb4dQab|g}Q?68+~j1%r2iTNN{b0147P+MSn*tSJJu!!xjLX}d6#ga=F65)h#Bu`Ln zK#At;dGlFqTRutk=Q>rueNqQI0j0%IGJ|ijW34k?NEOsNg(8{i%k1o^(@*)%f);KP zx`vFDwlT6nRrP&j3=Y?(TlxrR6u~!5*n@0q_JsVSV@f#Cl9@AE>XBUH)T9B!3LNg; z&Zt*=g}9~kry{0`cZ z%K!X?-0VIwJd&vt@C|uVGu{0H4z_h> zl~xfUQUv~(4dk|wk%57O1|4iHp`4K%fh<6Jks?i_wddd~uBcJnYSm1-YV-i696DZy zAQm2qs*d-R;+r^XK))y~?s-=?jD^faTWd4?`D!{MIY!~tWTODk%OdJU$yxePGzY) zqkEST(UoF0ap*J&*%xOdUc#z@w+>6%!i6ke0-04s$C3_F+9dks`bNVb&+`oHXao3; zU)eG$&03RA<_!M$9+JmATGghnMq*E4b$WP131Jp}=2dp;Z_K!17!ap0T-q!jAgw%yeN*RmcO+ z%8B)B(YDGx^K`+@<##eUJAPM_hp_PVE#}8^-_dF^rI8yA4+XgbL;J^&oF=-}s~Ry< zYGnttA4f2?`LluhrKMb)DZ*{6Bb4=2t!+_~4EiS_g9ejj3`-PXU?PB34hfH&xcoeO zw%vE1LV_e>@644dF{oN%tjSmvZ>0S3L1sJfQ>^vV&#P5=hyD47>93hP$X3c2h3Dw)`Qu597mu_mI;$bRa*T}UMZ#r zNkZLn>&&G#)vWF(YL-|RLn_0d&sVLUe8Fv68%0I)MO*1D!H(L(CK2-q!U>I}A)bm$ z#t8}#=ZW@`nalfC?l@{UwPtwKAzq|arHeWKT32=#6yZjfXI{gFw29$Ehb@HY#AGaB z66nPbn!`HBkUik9>yW%GdJtGu3GHr^-uNzd@t+(L8m^e!k6bPLhJ_x!l&|(Vf$jO& zig!@a?V3gs?!i~seG8qi*$6nMlV&jZI)gtJl}1Tw3-xgQqW@xRVZdu$QglWa?-Ye zF3&dJ+=E;o%nB9ooBA9(1!~eciQJy4cE$8bP{0AYDcO8^`I;u5XKQD1c*5`K{qIVa z-o7(9r4T}_r^PgMxV_5CFqT|qtA*VTt8Q2AKU-J3T53Ke-hnlE;%T5|;6#Q{_6Qa?KI<{LWCw483sI7- z^C%vz9e1EEvs98q{170Klr#Ws+(Jngp@cxhP|J5!sQXr!q>MY1iF_r!XBa-`tN!P$Nru z3LRQ*OMabl?WWd~?cMRNv(~L@+vkLaXj*>`KLy`S;VLZf6ncSULB`;Yl>Uhji^R-X zw=*1N3<*bbA`WO>LJnnADm_kZlbAhoUHM0~Nq&I*aY_tAsn;hbjg`4+4_sb`cg`=W%18v*Uo2ib&?zCoH%$X3b0H%Wd_M(scq_3 zj|m|=dsVKfcq(WWb&cHCF{>?j%qP(im?z3~RzEbxGOpJSvAD%7JCg0AnTi)TQ|SDa zzph&KW1eiD;~_}W|HLS{vE%B0b&XnB-5JRsyOz;Z9N_MfMBtTQKUd^g z>!A)etX)&~RpFPSFP0HJ-#{AK4`DVI@dUTF;Jv!Ll|I z2?6t?ElQq#Q=Yv+FDbT;+1qWTKrwrPEq??46^pD{<8l~%1OgI8`#aV~{x_`cUtx%% ztF6)hgd*oM)3PYsHmh@1C>Y56UxS9=>%C@zbVtxYI?d7gjZaiHpLK^^!lTPIn!+32 zB>Eu&MYc@d$hJLeyND7?#n(Oe&(^NTT5WugS=T5%LAhm4(|dUN{v4$_%3w9Usvj9$1clqM%(a8)tFMcp z5ZOU3pLPu(iT0xuZ8}bL;!crK%2ssO;D_9VGz2~)iv$aVq|5nCz^C}V87dnxWR)9? z9ww^R+w5Auz^)_hhn=pSzfhJMV`=baB8dAS22p4f+ueX=OgeJ+k?j&uOi^cOU!;(_ zNHG4IN#?SXt6(RTGG?~_HpZ%Y^{kQD-7*y}&UJFi=z8Q(2y_fLeO?62xJ^Ua%=arI zF69eIO#iU2@mj;C_0_DCuTMskLw{2v4clX#UmGW&dTngME|vC5I11 zD?`>MrnX2g$O6j>`YS-fixG&tBEq3EA&2rtkylXuMK-<@q+MI&-#(O(h~zQ$$k3m8 z1!Y2zaMPh)b<{u@cjG0-v?E8mVa%6w;*tC`FAOki#X8fI=Iwn(--6xXDWeb0oX(g! z^GZOa^&DyohH*up*|`}y!9**^>Q)457r(q^K=Z?8sP#2!_lzkGxedbGE2+r45oRWh zJr!r%cWHQhz`|~hMaToLc)&3maxo!ReZ)C}uY9`$yXeuFAB+sdZvThglGpY(>%B)C z5ukskw|^Hy|4VNb9Q7RkM{#4UekpGMTY~keG6lRsB&i&z9=4dUP!zQJ#r>&3hQ#08$ys{E-`m zF(6!>-JW~=a#o@KXgOV?doZflReH1tLPQrL+!sS|y~@+PBweebSiM!rK+VwytJG| z58cZ>s+;(}QvL!VLd<|?i6NC{4aEwyO`~G( zCNwFxwHs;+0XdQ_lp>Oih)t4A%vQ|arTFt8|K5eB7fjT+G0KgA-T`gXmx7sMT(+-^ zJQp}qvX+XL<29ZM4hOOLpM@oS2lDh_d^y~?f zTl@CC6lGD!FeWOl5f@`SEk6*WjF<0I?;Wxy@t(|2(!@9{1R6S*@GJzpegTY+dQ^B_ zE|4-k2qc0oBz|;p_rgRq^oFWcEFv(JYkduRK~|Dj@iTp~cHxKTj*9Tw6J#-9;#85T zixa~-k0*qB07X1n*`YBRP2DpR*<9E_?^s(J{87qWLrlY*i+V>&E{}#Vv*Vn|)*n}z z>)~`?gC6{BoPShVd=%%n{}M|Gz-yx@P`yPOZtr~kG%rYcb&0Di`1JbemuF_)E*TGg z*YNd!({L-xf3Hx|{GDeuG%+F)e!u)%@vv1{%K=#l(-eX$y(-};7Ge|- zb#*y0J{4$Ts9rQ#X_f#-{Kc^5l&MGHuUc+p^RFMktZ=PRgXn*XGTqV@=GygR*l5}QP%6^jWXj`4 zm7_y9@SyQzX7@S)BXJCY@;Lt3ZWsYZFh;|OVGLpDnBD)tSB`;tno}HluoKhYc8(?x zBe3ATKxmiz#q2#b{R?oDF`q%>6bzLnhpR_>TQGF6HWzLB%8p2{(>@5YI1kc z&PKZ(yZJ&Kabu4y>!PBahu~qTEmu`TQ44#;B_ue;Ez>fRC~x|-ErPhe@}VQYkyyg9 zAeMhr_R91lsvg=tH}SCeB0j7c`SIsP_UWOaWQJB^a;#a~T#~JjpV^`Q25e&ptgESq zvXdXzS5i^hGWB3c$vkpJ*)PdF293RFgML&#r)|rB6POzhfyp5LsY!FEL&#ar+&#L@ z%SIT~n!9O~di5c?tSMb7B!s5)dt!D{H-|w0*gzQ!*z2ObB*cHtNO- zO;e(&lI$lUVC52qP8{aTzgK<74Aecs{O(WxRv${#J}YTcMkfZ1)Ggp`W>A}nI6 z?8jOS_~Ygvn-XSd?kg{7(5Rf+?%`vR@=a>XMLd(GVC<5YHA9n>Zwu!q8~rziPYJcR zUj9&PS<{Y7bX5U4pzjY1i{yt=Uf76s`%tL^Hs?_x&31^2+d3ra0k;%j60{( zy6ApF;3?cXWTXI8kU$533lJp`Q1bg*i)mo z<=oOuC^2{u*HH5x28~jcW2%Q;tW;cPCDHxhOT&1m2{82Jn#K)=4EtDR9lpWr)8~+QL?kRfV!GK;e#;=xTXX>^yF zTgDJhuF;T!>3dql=~VRSa?gl-bgb0AsY(-@c8@d2@1yr&pz5Vp*iQV&CKBZ>m9rz} ziDoMa=4zn_>t*786g`Ke8ksDe>6#YoM-bq96Hsif95-WYPCMz0-3dogiLa9-!kQ(< zz}$>6AvHld>wQ$gS-Zs{jnqiVA>`E7t1k#qi9%qR8*W`Aa<|F>gQn}@(_5?61Bcvq zpdNZ!FtB?E68fQ*K&S61%x}ot535Uyxj6uS_KDD=bVO|TtB3aj?=N?q&;his@SggF zg8iM4{MlU-{2%W6pA5S7J^P8Rg8G_HZE;QHgu_{DAvn#HJH-~1+|-9CEonI{PVxl_ zi&J_#*@#MNN4&Nnrz!===vcrjz6`o1>x7z99AM-y;ML9k3?A@uf&2~h4LHDkJydkc z&~P6Iiq~|_(`K#p?&<7m?cnb1b=C$5X7dzM9TePNgreCH4az@Go%uRmTWr$6m7F!VOGIt*jG z;dH2S?3P(IQxWa4+VuMw_ZathxFgX^gI@4cIOp>Ovlb(dfrc?TF9ib4*g})=o|6pg z2X+(HIy=8x|6ql@R6cjP5<|)1fhF+K9xhCF{dh@tNnMI8DS$W|?{$yBOFx~Mh1TdJKnO&zm;raz#~KnYsis7JvvBo`viZdSs^ZpF-|GntxD z8gmZA*@yderL6l_-}7S~x&3fzdt8fvbC{&fae$R3~^WQzhIs+~dy&BZ! z&wC8hb!aFC2=+5A*^HY$8g=j!l3`a#P!nVcksL-_vUS&~ctB5Dp5oe+^KS0!J^DE< z+0AJ)P`S!WS>k$?$#7RuREAwedfwEuoj4iH&~Ww;WahVY%Q)-zQtiM{2BXSn1b26B zry@(}$!yIn*rHK+D0cQ=*io2yx~kQk@(DCEN0#qSlJW4jwsCeQXXua0K;uCESe*e; z8H$0z6Ql_)7@T`umGg+-AX(gr5pwm}YA`xf!F0Wf(l`~pNaZW|mL!F<(Vu{^l#m24 zb|5Nnxr1(b5?dVcYJ`8i?7qM%*%qt7melf4fc&OTf$o&K75ReRHr zc4bY94)>IC$H45UEi1i6o(^`l z>1K0Wo216QahyRjC&igqLJrQMb=)?bbFO<_A5S!ykf9a&C{2_yc37JEH&N04*ALuT z^|t*SYd`a67No}6!uWzqS4G*rL!`be__za+pAvHkNStTsgv8!XRwzl_MbAgxB-wiM zK)<2^HO;;X*%Y#_pr3~P?D2WQBR-`+yh}A)J$*R6eRd)|JUjE3kQbBiA@a-XDa6qd zL5)Gm2?i)SHx|B%yP#rCA9384yeQ?)2%!edtjVGZn%gu4>($b#_XaMZmrRwXyP)Qn z>$sze&XyY}NzP<`ioNOkH~`w1lIv(VFo|;3W9RnGTQ{}mt7*fh0^7tk+Qc<)(D>Vf zJZ?9$2<@eug#W$G>z4=r;432b1~-Xr#PL0pqal3zXakFh1h8$k=Z*}oMdWIXi=J4@ znU*lkbpH7HI$zFaqeWDoO|+L@5R44~=9G>xGWn?x8l(3;PahJ!Pt#xD&-lTIs43hBYx_I%o+&%&4LpCkSFc58GVe)8=SNR(e0EsfrT zFI;b62TBk=+maHpf-YOeu{aN2U+&Mq%@-kB%M!MThrNYxq<_F02aYW=0*e>V&tK`o zz`I`JOEBS~vqzrmrE$kC*`ciUFVT`I-HbVLhRwh)Iwm(sb}AU3Fn}F@G+QgpVc(j} z{l*GRFY$oA@9ahYh{JPE@fM<-v|KwjP;u#Z*s0vt627n118QPSr>MbM<4-$OTeq|{ z(Wl-}$I?=TR#b*~Tw$3QIu}3vWjO5%iOBqgQln}}KaZ=#t5@Mml>9X*N5z{Y=}(

4uhW@poR46Jknp0D(*qZ;O5m7T0mr5 zrq4ARwwS{Vs7v8kQY(L$^~lu(Rgp+tTQ!+2%sB@}8CWcwt_8jY+lPh`Qjr`nVB3X$ z2}f=`Zz74NNloOq*9c_x7}voPzvFQIam0Z*|yh)An11+hz2{KwXuk1Ty*TH0d>^U^+K=75Z}J@4zW?oOO`cAu{@2m zt$I2e^YE;%0dIh)qoH7=a*Ok%la&!)HQLLW($rvQG9X9XDN{n%Va^oj(=?#94WHu` z*jr-EXqt&!5zCWtAErd|SFctfYZ=DwaSK&dDw#IH1c%#u>Jh}kczev|y(~**V?g=2 zrZA0?Jd2RluhSa;u&9vY0FOI&syHAl(3>+WNwcWA?%3dPKDPN#fBAgsZ5h#=yt(NUb@HiC5Q&6XXpl@8mQ%NnjbB=2 zb&;;bVh`zCG>NsO#|6ZFPN=hSC5W(oGTdEy<9=$2!q?Zw*AE>A_eLlf$tGMFsUd88 z;)z*sS3L z8w^ZGcK&=;ii+dX0V6JGYKk+%L>4YC8<5D?8!}X+LKe=^?l;T`Eg1aXj$|(gu(qcH z!&o}KP}44H207lrKapz@ew;@+$f_x#EGZYLV4h!oZz*|VQ?%IOu%0+4EhhSw^D}HM zK&7w_Ppk7qKo;=}M+x15<6&u(ZkkyA0k9J@Y`qF%k8d&6sBV%gd}i}M72^}x0i{*8^CM>z=BqF4?LI9T%_n!hi861SCS{i~IzEVQ zg{k4j;cGU(Jb*4o-2I1lZHoK1l+B+#0OMb3)NdX@-@(!Tz1{myo*+$8Lk3$EWTU2dB zkprVf4Gd?(yovKrUGMbmNtG~vWR^j~xx?y?UuoNqYRaiPZ#4fb|DbRc80v>+G}>JZ zn!aPgANBxeocvsiDYQHWLFW~((gpvbadotBXskml>@_4|mR`%K06N1Lk92;6812bL4nfPVBP6@kV4tmFr5$jB88Bd3WA&* zD2|MdkCh6Oeq+jX9;I2R#hPjJw&0)WYx={yRm*preQU>@C8yBC(Wh5dHsbNyxeX@9 zFcm+oii-QtMElFCEogtD5$2H%IPf=g68G_r4CaTS#Lz#mz{uT%;wV&%|D2gSY9$wM zo`a=7wU){PR*w?OplLdRAH+gqvGA!&$-nxTeUg^a%C>slOOD?Acxn^8J5KERMpt@P zBO5!q-`9Wqg8gTR2?LWhPt+u}xm7&>FqHdbWEct>vq?VmgQBKzib^UcR<)QNLEI+713c_)c?kHiQRddBDuz8_O zz9(oFu<_27%0}%__*P(MPEqwRuLy1_ZgMqQd#Ny$ZUOgV?fQ8Pe%&)%laDk!;KpT8 zp&tpYG^A~xtn>=#@rNv>cNF$eq!4R$hG-O5wA_mFxAFjFKCP4n#*xBwe@!dfFV%-# zAEuY^?Z8Y{R8pV9V#rLcxsVq}F_rFn-kD3{VwavO^~ZtXuy&eUbcJQLTg9K)_I3f?If~DT)I+K_8&~4pm0ik@%Uu>t+)vL* zY7GU0l>8ADPm!-yFdg-uFgvUxBS-SW!q)g;><9QtX&bO z>QWT^bPg`@1)N06Ag*XIFIAFG%TYU+bq6`qnWiPyc9DiR;Hz(KZ2$c3d33q{3p2~N z{yF?MXx?)Df?(2*hnz=CB3v=!2N7;DZ%0D)oHrz%yN45Krmqr#+Yp9&?5R&$+N6RR z-88qUlzg%?c;qeHcsK2IMY1m#yHStO|7`xk3pc_{diQ#;P`}PnU=S3bKL%=kpM?1} zQ1kEd-^OcxNBQMJe{bghH8t~x=)K?m|Ig6;8UOdDOrk%)-|u$bM+p8N|DPn_&xpS_ z#QiEn{UILjyY$}>|FgC8&$z#rY=5=W{UP%2xu?Iy{p*GPUQ7E`>HR|>(f>Q(f7E^d zyw2YX82|qJJKl$){@XhLvn=;J?yr2>@0qq=<&Qrk8|QCu|FRhJXYAiO{I6WyA0qeu z_+Qujj{VnL`#Z<{#r*#eh4(G_PrTn)z`w@{GzCT$Oo#w0{#> getRequirements() { @Override public void perform() { System.out.println("jetz mach ich hier die übelste Welle!"); - + for(Edge e : mGraph.getEdges()) { + e.setCustomLabel("hallo"); + addStep(); + } } @Override diff --git a/src/DepthFirstSearch.java b/src/DepthFirstSearch.java index 1f3491a..b4a2a0f 100644 --- a/src/DepthFirstSearch.java +++ b/src/DepthFirstSearch.java @@ -43,6 +43,18 @@ public void setRequirements(ArrayList requirements) { @Override public void perform() { + + /* + * error state + for(Edge e : mGraph.getEdges()) { + if(!e.isDirected()) { + addStep("this algorithm just works on directed graphs!"); + return; + } + } + */ + + for(Vertex v : mGraph.getVertices()) { v.setState(ElementState.UNVISITED); } @@ -52,7 +64,7 @@ public void perform() { dfb = new HashMap(); dfe = new HashMap(); mD = new ArrayList(); - System.out.println("starte tiefensuche mit Vertex "+ mStartVertex); + System.out.println("start depthfirstsearch with vertex "+ mStartVertex); depthFirstSearch(mStartVertex); addStep("red = Tree Edge\ngreen = Back Edge\nblue = Cross Edge\nyellow = Forward Edge"); } diff --git a/src/Dijkstra.java b/src/Dijkstra.java index 316808b..6c2d0d3 100644 --- a/src/Dijkstra.java +++ b/src/Dijkstra.java @@ -23,7 +23,6 @@ public class Dijkstra extends AbstractAlgorithm { @Override public ArrayList> getRequirements() { ArrayList> requires = new ArrayList>(); - requires.add(new Pair(ElementType.VERTEX, "Source Vertex")); requires.add(new Pair(ElementType.OPTIONAL_VERTEX, "Destination Vertex")); @@ -86,7 +85,6 @@ public void perform() { showShortestPath(); addStep("show the shortest path"); - System.out.println("FINISHED!"); } @@ -101,9 +99,7 @@ private void initialize() { mDistAndPrev.put(v, new Pair(null, Double.POSITIVE_INFINITY)); updateLabel(v); mQ.add(v); - System.out.println(v.getLabel()); } - System.out.println(mQ); } diff --git a/src/PushRelabel.java b/src/PushRelabel.java new file mode 100644 index 0000000..02e3695 --- /dev/null +++ b/src/PushRelabel.java @@ -0,0 +1,421 @@ +import java.awt.Color; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.prefs.BackingStoreException; + +import de.chiller.vigral.algorithm.AbstractAlgorithm; +import de.chiller.vigral.graph.Edge; +import de.chiller.vigral.graph.ElementState; +import de.chiller.vigral.graph.ElementType; +import de.chiller.vigral.graph.Graph; +import de.chiller.vigral.graph.GraphElement; +import de.chiller.vigral.graph.Vertex; +import de.chiller.vigral.util.Pair; +import edu.uci.ics.jung.graph.util.EdgeType; + + +public class PushRelabel extends AbstractAlgorithm { + + private Vertex mSrcVertex; + private Vertex mDestVertex; + + private Graph mResidualgraph; + private Graph mBackupGraph; + + private HashMap mHeight = new HashMap(); // for vertices + private HashMap mExcess = new HashMap(); // for vertices + private HashMap mFlow = new HashMap(); // for edges + private HashMap mRestCapacity = new HashMap(); // for edges + + + + + @Override + public String getAlgorithmName() { + return "Push-Relabel"; + } + + @Override + public ArrayList> getRequirements() { + ArrayList> requires = new ArrayList>(); + requires.add(new Pair(ElementType.VERTEX, "Source Vertex")); + requires.add(new Pair(ElementType.VERTEX, "Destination Vertex")); + + return requires; + } + + @Override + public void setRequirements(ArrayList requiredElements) { + mSrcVertex = (Vertex) requiredElements.get(0); + mDestVertex = (Vertex) requiredElements.get(1); + } + + + @Override + public void perform() { + + createResidualGraph(); + + // for all edges (u, v) in E do f(u, v) = 0 + for(Edge e : mResidualgraph.getEdges()) + mFlow.put(e.getId(), 0.0); + + + for(Edge e : mGraph.getEdges()) + mRestCapacity.put(e.getId(), e.getMaxCapacity()); + + // for all neighbors v of s do f(s, v) = c(s, v) + for(Edge e : mGraph.getOutEdges(mSrcVertex)) { + mFlow.put(e.getId(), e.getMaxCapacity()); + mFlow.put(mResidualgraph.getEdgesFromTo(mResidualgraph.getVertexById(e.getEndVertex().getId()), mResidualgraph.getVertexById(mSrcVertex.getId())).get(0).getId(), e.getMaxCapacity()); + mRestCapacity.put(e.getId(), e.getMaxCapacity() - mFlow.get(e.getId())); + } + + + // for all nodes v in V - {s} do height(v) = 0 + for(Vertex v : mGraph.getVertices()) + mHeight.put(v.getId(), 0); + + // height(s) = V + mHeight.put(mSrcVertex.getId(), mGraph.getVertexCount()); + + + // edit labels and hide non existing edges (set custom color to white) + updateResidualgraph(); + + + // mark s and t as visited + mResidualgraph.getVertexById(mSrcVertex.getId()).setState(ElementState.VISITED); + mSrcVertex.setState(ElementState.VISITED); + mResidualgraph.getVertexById(mDestVertex.getId()).setState(ElementState.VISITED); + mDestVertex.setState(ElementState.VISITED); + + + // save snapshot of the graph an the resulting residual graph + addStep("after initializing"); + addResidualGraph("the resulting residual graph"); + + + // get first active node + Vertex activeNode = getActiveNode(); + + + while(activeNode != null) { + // change color of active node and save a snapshot of the resulting graph + activeNode.setState(ElementState.ACTIVE); + mGraph.getVertexById(activeNode.getId()).setState(ElementState.ACTIVE); + addStep("choose Node "+ activeNode +" as active node, because:\nexcess("+ activeNode +") = "+ excess(activeNode) +" > 0"); + + // search for an admissible edge + Edge admissibleEdge = getAdmissibleEdge(activeNode); + + // if there is an existing admissible edge (v, w) ... + if(admissibleEdge != null) { + // change color of admissible edge in residual graph + admissibleEdge.setState(ElementState.ACTIVE); + addResidualGraph("residual graph:\nchoose edge "+ admissibleEdge +" as admissible edge, because:\nheight("+ admissibleEdge.getStartVertex() +") = height("+ admissibleEdge.getEndVertex() +") + 1"); + + // change color of admissible edge in result graph + if(mRestCapacity.containsKey(admissibleEdge.getId())) + mGraph.getEdgeById(admissibleEdge.getId()).setState(ElementState.ACTIVE); + else { + int startid = admissibleEdge.getStartVertex().getId(); + int endid = admissibleEdge.getEndVertex().getId(); + mGraph.getEdgesFromTo(mGraph.getVertexById(endid), mGraph.getVertexById(startid)).get(0).setState(ElementState.ACTIVE); + } + + // ... then push(v, w) ... + push(admissibleEdge); + } + // ... else ... + else { + + addResidualGraph("residual graph:\ncall relabel("+ activeNode +"):\nbecause Node "+ activeNode +" has no admissible edges"); + + // ... relabel + relabel(activeNode); + + updateResidualgraph(); + addResidualGraph("changed height of node "+ activeNode +" to minimum height of accessible nodes + 1 = "+ mHeight.get(activeNode.getId())); + } + + // save snapshot of resulting graph + updateResidualgraph(); + addStep("the resulting graph"); + + // restore color of active node and admissible edge in resulting graph and residual graph + if(admissibleEdge != null) { + admissibleEdge.setState(ElementState.UNVISITED); + if(mRestCapacity.get(admissibleEdge.getId()) != null) + mGraph.getEdgeById(admissibleEdge.getId()).setState(ElementState.UNVISITED); + else { + int startid = admissibleEdge.getStartVertex().getId(); + int endid = admissibleEdge.getEndVertex().getId(); + mGraph.getEdgesFromTo(mGraph.getVertexById(endid), mGraph.getVertexById(startid)).get(0).setState(ElementState.UNVISITED); + } + } + activeNode.setState(ElementState.UNVISITED); + mGraph.getVertexById(activeNode.getId()).setState(ElementState.UNVISITED); + + // search for another active node + activeNode = getActiveNode(); + } + + // save snapshot of resulting graph + addStep("The result, because there are no more active Nodes"); + } + + + + /** + * saves a snapshot of the residual graph with an explanation + * @param s + */ + private void addResidualGraph(String s) { + mBackupGraph = mGraph; + mGraph = mResidualgraph; + addStep(s); + mGraph = mBackupGraph; + } + + + + + /** + * updates the custom labels of the vertices and edges of the resulting and residual graph + */ + private void updateLabels() { + for(Edge e : mGraph.getEdges()) + e.setCustomLabel(mFlow.get(e.getId()) +" / "+ e.getMaxCapacity()); + + for(Edge e : mResidualgraph.getEdges()) + if(mRestCapacity.containsKey(e.getId())) { + if(mRestCapacity.get(e.getId()) != 0) + e.setCustomLabel(""+ mRestCapacity.get(e.getId())); + else + e.setCustomLabel(" "); + } + else { + if(mFlow.get(e.getId()) != 0) + e.setCustomLabel(""+ mFlow.get(e.getId())); + else + e.setCustomLabel(" "); + } + + for(Vertex v : mResidualgraph.getVertices()) + v.setLabelAddition("["+ mHeight.get(v.getId()) +"]"); + + for(Vertex v : mGraph.getVertices()) + v.setLabelAddition(""+ excess(v)); + } + + + + + /** + * hide the non-existing edges in the residual graph by changing the color to white + */ + private void updateResidualgraph() { + for(Edge e : mResidualgraph.getEdges()) { + if(mRestCapacity.containsKey(e.getId())) { + if(mRestCapacity.get(e.getId()) == 0) + e.setCustomColor(Color.WHITE); + else + e.resetCustomColor(); + } + else { + if(mFlow.get(e.getId()) == 0) + e.setCustomColor(Color.WHITE); + else + e.resetCustomColor(); + } + } + + updateLabels(); + } + + + + /** + * creates the residual graph + */ + private void createResidualGraph() { + mResidualgraph = new Graph(mGraph); + Collection edges = mGraph.getEdges(); + for(Edge e : edges) { + Vertex start = e.getStartVertex(); + Vertex end = e.getEndVertex(); + Vertex startRest = mResidualgraph.getVertexById(start.getId()); + Vertex endRest = mResidualgraph.getVertexById(end.getId()); + mResidualgraph.addEdge(Edge.EdgeFactory.getInstance().create(endRest, startRest, true), endRest, startRest, EdgeType.DIRECTED); + } + + for(Edge e : mResidualgraph.getEdges()) + System.out.println(e); + + System.out.println(mGraph); + } + + + /** + * searches an amissible edge in the residual graph + * @param v the vertex to what an admissible edge is requested + * @return returns an edge of the residual graph + */ + private Edge getAdmissibleEdge(Vertex v) { + + for(Edge e : mResidualgraph.getOutEdges(v)) + if(mHeight.get(v.getId()) == mHeight.get(e.getEndVertex().getId()) + 1) { + + Double rest = mRestCapacity.get(e.getId()); + // if e is a forwardedge and it exists in the restgraph (restcapacity > 0) + if(rest != null && rest > 0) + return e; + // else if e is an backwardedge and it exists in the restgraph (flow > 0) + else if(rest == null && mFlow.get(e.getId()) > 0) + return e; + } + + return null; + } + + + /** + * searches an active node in the residual graph + * @return returns an active node of the residual graph + */ + private Vertex getActiveNode() { + + for(Vertex v : mResidualgraph.getVertices()) { + if(v.getId() != mSrcVertex.getId() && v.getId() != mDestVertex.getId()) { + if(excess(v) > 0) + return v; + } + } + + return null; + } + + + + /** + * changes the flow of the given edge + * @param e the edge to be adjusted + */ + private void push(Edge e) { + Vertex v = e.getStartVertex(); + Vertex w = e.getEndVertex(); + + + // if (v, w) is in E then... (if e is a forwardedge) + if(mRestCapacity.containsKey(e.getId())) { + Edge g = mResidualgraph.getEdgesFromTo(w, v).get(0); + + // f(v, w) = f(v, w) + min{excess_f(v), c_f(v, w)} + double flow = mFlow.get(e.getId()) + min(excess(v), mRestCapacity.get(e.getId())); + + // remember old values to be able to print them later on + double oldflowE = mFlow.get(e.getId()); + double restE = mRestCapacity.get(e.getId()); + double oldExcess = excess(v); + + // apply the new values + mFlow.put(e.getId(), flow); + mFlow.put(g.getId(), flow); + mRestCapacity.put(e.getId(), e.getMaxCapacity() - mFlow.get(e.getId())); + + // save snapshot of residual graph + updateResidualgraph(); + addResidualGraph("adjust flow of edge "+ e +" to "+ oldflowE +" + min("+ oldExcess +", "+ restE +") = "+ flow); + } + + // ... else e = (v, w) is in E(G_f)\E(G) and e is backedge of g in E(G) ... (if e is a backwardedge) + else { + Edge g = mResidualgraph.getEdgesFromTo(w, v).get(0); + + // f(g) = f(g) - min{excess_f(v), c_f(e)} + double flow = mFlow.get(g.getId()) - min(excess(v), mFlow.get(e.getId())); + + // remember old values to be able to print them later on + double oldflowG = mFlow.get(g.getId()); + double oldflowE = mFlow.get(e.getId()); + double oldExcess = excess(v); + + // apply the new values + mFlow.put(g.getId(), flow); + mFlow.put(e.getId(), flow); + mRestCapacity.put(g.getId(), g.getMaxCapacity() - mFlow.get(g.getId())); + + // save snapshot of residual graph + updateResidualgraph(); + addResidualGraph("adjust flow of backedge "+ g +" to "+ oldflowG +" + min("+ oldExcess +", "+ oldflowE +") = "+ flow); + } + } + + + /** + * adjust the height of the given vertex + * @param v the vertex to be relabeled + */ + private void relabel(Vertex v) { + + int min = Integer.MAX_VALUE; + + + // height(v) = min{height(w)+1 | (v, w) in E_f} + for(Edge e : mResidualgraph.getOutEdges(v)) { + // if e is a backwardedge + if(mRestCapacity.get(e.getId()) == null) { + if(mFlow.get(e.getId()) > 0 && mHeight.get(e.getEndVertex().getId()) < min) + min = mHeight.get(e.getEndVertex().getId()); + } + // else if e is a forwardedge + else { + if(mRestCapacity.get(e.getId()) > 0 && mHeight.get(e.getEndVertex().getId()) < min) + min = mHeight.get(e.getEndVertex().getId()); + } + } + mHeight.put(v.getId(), min+1); + } + + + /** + * calculates the excess value of the given vertex + * @param v the vertex + * @return returns the excess value + */ + private double excess(Vertex v) { + + double in = 0; + double out = 0; + + // sum the incoming flow + for(Edge e : mGraph.getInEdges(mGraph.getVertexById(v.getId()))) + in += mFlow.get(e.getId()); + + // sum the outgoing flow + for(Edge e : mGraph.getOutEdges(mGraph.getVertexById(v.getId()))) + out += mFlow.get(e.getId()); + + if((in - out) < 0) + return 0; + return in - out; + } + + + /** + * calculates the minimum of two double values + * @param a the first double value + * @param b the second double value + * @return returns the minimum as a double value + */ + private double min(double a, double b) { + if(a < b) + return a; + return b; + } + + +}