gower/0000755000176200001440000000000013466626147011414 5ustar liggesusersgower/inst/0000755000176200001440000000000013466614147012366 5ustar liggesusersgower/inst/tinytest/0000755000176200001440000000000013465343450014244 5ustar liggesusersgower/inst/tinytest/test_gower.R0000644000176200001440000001022713460534474016556 0ustar liggesusers ## distance between logicals dL <- expand.grid(c(TRUE,FALSE),c(TRUE,FALSE)) x = data.frame(x=dL[,1]) y = data.frame(x=dL[,2]) expect_equal(c(0,1,1,NaN), gower_dist(x = x,y = y)) ## distance between factor variables bands <- c("Grand Magus","Skull Fist") dF <- expand.grid(bands,bands) expect_equal(gower_dist(data.frame(x=dF[,1]),data.frame(x=dF[,2])),c(0,1,1,0)) ## distance between numerical variables dN <- data.frame(x = as.numeric(1:4),y=as.numeric(c(1,1,2,3))) expect_equal(gower_dist(data.frame(x=dN[,1]),data.frame(x=dN[,2])),c(0,1/3,1/3,1/3)) ## distance between character variables dC <- data.frame(x=letters[1:3],y=letters[3:1],stringsAsFactors=FALSE) expect_equal(gower_dist( data.frame(x=dC[,1],stringsAsFactors=FALSE) , data.frame(x=dC[,2],stringsAsFactors=FALSE)),c(1,0,1)) ## multivariate dataset bands <- c("Grand Magus","Skull Fist") dL <- expand.grid(c(TRUE,FALSE),c(TRUE,FALSE)) dN <- data.frame(x = as.numeric(1:4),y=as.numeric(c(1,1,2,3))) dF <- expand.grid(bands,bands) dM1 <- data.frame(x=dL[,1],y=dF[,1],z=dN[,1]) dM2 <- data.frame(x=dL[,2],y=dF[,2],z=dN[,2]) expect_equal(gower_dist(x=dM1,y=dM2), c(0,7/9,7/9,1/6)) # check symmetry expect_equal(gower_dist(dM1,dM2),gower_dist(dM2,dM1)) # not counting NA's in the denominator dM1[array(c(2,3,4,1,2,3),dim=c(3,2))] <- NA expect_equal(gower_dist(dM1,dM2), c(0,3/4,3/4,0)) #auto-matching columns expect_equivalent(gower_dist(women, women[1]),rep(0,nrow(women))) ## ignoring column name cases",{ dat1 <- iris[1:6,] dat2 <- iris[1:6,] names(dat2) <- tolower(names(dat2)) expect_equal(gower_dist(dat1, dat2, ignore_case=TRUE),rep(0,6)) ## recycling expect_equal(length(gower_dist(x=iris[1,],y=iris)), nrow(iris)) expect_equal(length(gower_dist(x=iris,y=iris[1,])), nrow(iris)) expect_equal(length(gower_dist(x=iris[1:3,],y=iris)), nrow(iris)) expect_equal(length(gower_dist(x=iris,y=iris[1:3,])), nrow(iris)) ## weights expect_error(gower_topn(women, women, weights=-(1:4))) expect_error(gower_dist(women, women, weights=c(NA,1:3))) d1 <- women[1,] d2 <- women[2,] w <- c(1,2) r <- sapply(women, function(x) abs(diff(range(x)))) d12 <- (w[1]*abs(d1[1,1]-d2[1,1])/r[1] + w[2]*abs(d1[1,2]-d2[1,2])/r[2])/sum(w) wom2 <- women wom2[1:2,] <- wom2[2:1,] expect_equivalent(gower_dist(women,wom2, weights=w)[1], d12) ## edge cases and exceptions expect_warning(gower_dist( x = data.frame(x=c(1.2,1.2,1.2)) , y = data.frame(x=c(1.2,1.2,1.2)) )) expect_warning(gower_dist( x = data.frame(x=c(1.2,1.2,1.2)) , y = data.frame(x=c(1.2,1.2,1.3)) , eps=0.2 )) expect_warning(gower_dist(data.frame(x=rep(1,100)), data.frame(x=1,100))) expect_error(gower_dist( data.frame(a = letters[1:3], stringsAsFactors = TRUE), data.frame(a = letters[2:4], stringsAsFactors = TRUE) )) expect_error(gower_dist( data.frame(a = letters[1:3], stringsAsFactors = FALSE), data.frame(a = letters[2:4], stringsAsFactors = TRUE) )) suppressMessages(out <- gower_dist(data.frame(x=1:3), data.frame(y=1:3) )) expect_true(identical(out,numeric(0))) suppressMessages(out <- gower_topn(data.frame(x=1:3),data.frame(y=1:3)) ) expect_true( identical(out$distance, matrix(0)[0,0]) ) expect_true( identical(out$index, matrix(0L)[0,0]) ) ## Top-n ## gower_topn d1 <- iris[1:3,] d2 <- iris[1:7,] L <- gower_topn(d1,d2,n=4) expect_equal(length(L),2) expect_equal(dim(L[[1]]),c(4,3)) expect_equal(dim(L[[1]]),dim(L[[2]])) expect_equal(L[[1]][1,],1:3) expect_equal(L[[2]][1,],rep(0,3)) # case where n exceeds nr of records in the lookup table. L <- gower_topn(d1,d2,n=8) expect_equal(L[[1]][8,],rep(0,3)) expect_equal(L[[2]][8,],rep(Inf,3)) ## just to get code-coverage right dat1 <- data.frame( x = as.factor(sample(letters,2000,replace=TRUE)) ,y = sample(LETTERS,2000,replace=TRUE) ,z = as.integer(1:2000) ,w = sample(c(TRUE,FALSE),2000,replace=TRUE) , stringsAsFactors=FALSE ) i <- sample(2000) dat2 <- dat1[i,] gower_dist(dat1,dat2) ## warning on recycling expect_warning(gower_dist(iris[1:3,],iris[1:2,])) expect_warning(gower_dist(iris[1:2,],iris[1:3,])) ## regression tests ## topn w/n=1" dat <- data.frame(x = c(NA,2,4,5), y = c(6,7,NA,10)) L <- gower_topn(dat[c(1,3),],dat[c(2,4),],n=1) expect_equivalent(as.vector(L$index),c(1,2)) gower/inst/doc/0000755000176200001440000000000013466614147013133 5ustar liggesusersgower/inst/doc/intro.R0000644000176200001440000000304713466614147014415 0ustar liggesusers### R code from vignette source 'intro.Rnw' ################################################### ### code chunk number 1: intro.Rnw:34-35 ################################################### options(prompt=" ") ################################################### ### code chunk number 2: intro.Rnw:68-72 ################################################### library(gower) dat1 <- iris[1:10,] dat2 <- iris[6:15,] gower_dist(dat1, dat2) ################################################### ### code chunk number 3: intro.Rnw:77-78 ################################################### gower_dist(iris[1,], dat1) ################################################### ### code chunk number 4: intro.Rnw:87-92 ################################################### dat1 <- dat2 <- iris[1:10,] names(dat2) <- tolower(names(dat2)) gower_dist(dat1, dat2) # tell gower_dist to match columns 1..5 in dat1 with column 1..5 in dat2 gower_dist(dat1, dat2, pair_y=1:5) ################################################### ### code chunk number 5: intro.Rnw:97-98 ################################################### gower_dist(dat1, dat2, ignore_case=TRUE) ################################################### ### code chunk number 6: intro.Rnw:106-109 ################################################### dat1 <- iris[1:10,] L <- gower_topn(x=dat1, y=iris, n=3) L ################################################### ### code chunk number 7: intro.Rnw:125-127 ################################################### gower_dist(women[1,], women) gower_dist(women[1,], women, weights=c(2,3)) gower/inst/doc/intro.pdf0000644000176200001440000035427613466614147015002 0ustar liggesusers%PDF-1.5 % 30 0 obj << /Length 497 /Filter /FlateDecode >> stream xڍM0m"q|A rZqېVU6-wlwvُ43I˅~zx:AAN~j"+7Fz_S5b]-MSa.ٽeXKK+l5o`=$740;6` }m\ R{\(!mTAc9lJ"ct\KxG URrgwm[cQ̀N rʺ&Jr^QH(MS7IY7/EΤUԑ8S-HTuVC> MN7&m"8lv?L})..$E #< 5)7 ݅+݁i|S) iyS.>x+OnfMk_(H_KGܤ??a/sϜc izY?]OF߾vz` ȩ؞#F52m8i/| endstream endobj 42 0 obj << /Length 1807 /Filter /FlateDecode >> stream xڝnF୔ dKRF V7(hUv";]2m'=HgUTtua~/tڬ0>&O]UFES|]zhT|YY7f:ng-xzO[ָxlf߀XiVHLERUfL 35Gz"0$:] Ḉf)#7KmqΒDdB6ͳxby%\',Jcå Pwk:w`π\\Ir8~ˮC(4OC,'n , jɲܦS&2sU#Y{t9dr ; 8rFE ڥc?7*W,0@螕T0lqڏ6;U&SBi阀lؐ<`N=pGОDY{9!a!VZ !zd둵(ځ{_,랽\M֫ndp̓WzI̾:,t4 ^h8*W53+4Qb`C̞e*0 _:0z;1$YΒ)Kky@ߋ,P$wqr͋xYfNܤtҸKPq/X+ T_eQ;\1q@W6=8<8f{?^s<E@NM{w;tZ]r1Z{: KWzW5Y @ӒgTI7k/u>JR#n<*k*6;)=l`o:RN>R5mMZ0ElQJM]JU޼n!^7*5oP);`gjZZySHQmE=ӔXRW}mG9{]KΝ!@hy̰bk|+ $/]ʀQ=0Wv~ltKբr,`H Syc0w]jBO%Yzn֌ȳazgaj,7;DUnI=C=u.z]F=W^.SԨ +ғ&l$Y=TBl*uUH15tG)$/YpVdX|[J58=Yc#ZY/D[sK u3(m# _[Ƿo6__CuJ_1 ..@ ,xQ2.El{W/|f<X؜lLlU#ϰy ®47 ?H\y?Sطnfxpl0n+2GPd>|wkrF3U aLmiGghJ}P`MhߤG:ֆzG'z[|g4ؠp0|j"]aAGZ-)_l#<튴Pm|<w)W endstream endobj 53 0 obj << /Length 1158 /Filter /FlateDecode >> stream xXYoF~ ЇR@݃gѾHy ԧh:D*}gfgy˱aØα3|(̔x*LE^)ak>ۅ++Pt @ I^:>)w@ "m;gNe~M T"Ty EIN潕j|G;G5I)+FOm fhĶާ } Qy'zG\ļQwIs3~p J0q"б_5=TJElV\2Zm/GSv7rdid˭SU ѹ^ ȹ;!]k{|Ciګ "F{ &/g9SgJI#L :HSqKǹxL86d)s5T${NMNŎ_"Hb/c׷)^yՊzZ2:J.غB{;68qQ[=l/R̕l2wbn^sUwT">u.jbָA^tҡU(3EB#H]r1n~D $*ؖUCZ]mR$`Z1ӎCP}lГ.s-/Y_[9+(IѰe & ׄ cGSEjaVJJ7;Bӹ4mbTS6vƮظS5*9,KLCmͅ"0x-)V]93bhY;RH p-`D]!l<'~2g> bg+{ڜydtWFFv^9"CNMDE}˻ endstream endobj 57 0 obj << /Length 1577 /Filter /FlateDecode >> stream xn9ޯaZ[3m{b؎ {4$Ehf4nЃ DMd;Oo$o}tae&NxvdL=5 /' seu>#As!F85[ ƗinooVoUzJFA֘*nme;ΚgóytgWu;xeNP-Q,ֹC^u%\g+>"0ޡ.OL Eȝ#1iIG>(M -kEW~bV9sc l5yYO7.~ dR*iGX0\Ǭ=a|%0 ꁹ&bޣc4*cݒ*=iWvT*RVMG̺VNh=x .W‡U^fj?EŷJK!>+0Ikdk"ePw@=nԹT*IU(cBm?,|]i!KZ+wd}Yd>'~jZ5:NFh}R&T)o`z?=lbhd:LJPh0>a[Eq.6ey:BQo@vQT1s8I.QۍUPeAR)emD0v=, !Z⦕w|ɣia϶Cq,$.-.cEyMK~/sDef2xXgm#f9%| 2z{%.$*?]I9E?lXLmM~Y>uMX]qҺHeEtfAO|-9>jU2"@ǦSMen:v#]X& k5g B}bxPL6 i[2'Il/oCa=F*iX wE!> stream xڕWKo6W(Jzzh,Rm"+2,e(Jv)r83!WJWVa =a^0ƻ+^NA%b(ވ4 =AER-Ё'1ƾV9(6$% ψh9cϼN؏ n'~.*@[Fe ;P`R1xh`8ʊc=EaKio*U1L0 I6hシ0`eC,HFA2(?Յ0݋7QCG;p^I8_tԨG"i7]՜oC踗GsW`9*$86#WN-Z d̓78#WyHEwy₣( X"䒽| 7I?#jpd ˃\xP+kb+ӓ ]wti\[aǛ9r{j~s9zyi LCD4$|u :JܷĿ!],зS8xQtXݛE.TBڙF_ehITDlVVkwUW 05Q]x=/!ydQy! *<̅F%0s0,X\ 2/$23S2G^$`#ݳ{ zqt࿈p8 s=D4^Ќ*Bslva:5,{w[<[J",>pYJC4Gl,  endstream endobj 77 0 obj << /Length1 1423 /Length2 6556 /Length3 0 /Length 7525 /Filter /FlateDecode >> stream xڍwT6ҤTNTI*]&!@(IH"wޛtAHtHrZ߷Vg3{?ϻpܾgįhԐ,?H(P@(Da :q8!e4 TXPh=r 1)%"R+B"`2e$ w{ r@|.04 FtX nG(`aXqbQR`m/pc0 vM`!`4 s8á0a Cp4u(7X7p пY B.(0a}5F1H\> wCp_j0n?ah8 ( UH!ٟ  S:!-;8P&# Eo= J K`Aƞ(د 77 ƀ`2o |3O ¡XfG: m q??ZYfD8{=TO *)!=B~!Q s j"쐀~;{vC? G]L/R4YewW7]Ξ8>dĉP3ol\;䠈Q$"c0{p,7m~M~ Cb?1, b8Ap C` Nr_ӆD>TPO h4ؓ w8K AKf!d?/ZB hN6qD2)[pm? }@Bk[dS X`{TG⍲2'K>wԬ\g?z/ղy𳩭ڳAb'.%x2ߙh{f*UEA*okcAWMקwN5qVL:fIo_ ͐~e=r< ZHK-vL^E97?MRgVZe:w,m#NaS6ǝ|TadžmqDh7c*4R*:7%v*;O.cڕx=[I+,Dsrkxv`.>xًobB[NZR^ ewΚ> 32Huh5+ nO%,| ZirCk^"ymmJUQhig' 7uд^. >U :}.B VTOR1-w*YcmJrN"[JO67zd:/{7MGz>]~kIqQ 7L4{ѵ,QKR--M\Wp姙zr=֠?h-it^sN k%$Ͽfn 31f`3of\"o(1̝&RCVy5C5~wpbǶЏfhr*;$SYq=nnֽ9> /A5gj}lb!;mC9;5=hRC8R.G& k&g/ӵU|;u L'9. .(9/-C)FӧN|Vѐ$`!"Jċ4DӧC'mI+kPL̲6'lƪ~KKtTg%񨚽,ۦ mE )>J-ޅj?噞z*jN[s=r`^2(FyH3Da0N6|ݮAfQ(S, %e"wP-'njǩ?0"r#gMzC_ ~̭ %8P4rU?''@3Tge> Eƚk&AѲIOyt787 2y?/厸Wl݉op"wu$[2:!$}օJkOMZBbs˫+ 疁CPSlz;ЉERG^rW)Q&Xm [+˓kzY`}{ThCVޜ#e xi޼=,|EC̞f2 .5z(,E/@}tt 5d&F9͔m YBKmw贗nSUV<ڟ_X}zNSϨ/S&+PZ(Yt:Zo,s!_ i5Sb~o#?{/g|xSKFI=N6W!+]wcͱ;ˉ|I@bX8movQ'~$̠E )WWM؂Qw G]x5N5s("!4^fjk^eU;}%9%3q1NUތ׏" x?a)lAAG:91{:tbřTd,tÜO5#03L"tf$2Dmǒ Pe0WəĘ>nRėּ^+䓠6>G;1\ROw<'S$/<+R"i?3ـZdb*[YxxB˯użb\-@\55+8JV]Q#5=./LH wy I_iܠfz;f Ta^hNyA!*#J硣]15y^CNf]NJ Wr "fr"s >S~y4z֘/'Yj]UoxJ^~$Xa/T*%*դDΔ=2z$%$pə+ZQ9rj}ٜݛTwR%jFaֺ@񯕏[F;I a.c*11(;;%\>$mӓGO<_҆k=HĠ^t?ACN9i-1Źñ>6G)Ar[xk_^q1Y|mPZYHX_͎"p]s†KfZcٍgcW&=ow0ZC|,^c5ׯn ,,^za݋eU1?y-s>>*|Lʻæ ;;%]4^M#{l0Q9vpp}&/zΰߪv[9|ZvhJ@F0V%|p:/xW wA+]w8Clhg_YL5|sq_hAB{?VYi7f9+q U-BVB. r1O}e]P` џϻ0M VAE` xe)[Q6+`VFvV&4UucۋDw.ڣ/bSsN*6 `,5*C^;@i.݆OcAO> 2 AdBϝN׆C4O,~+P砊@ m.5t85`]L2r;oIt~]bYr֫ewfW7>z]LhEj$TEbȻvWŔ?iN=~$Eq$+ɾ{={OXIbv)\z [C j)^h0^iZz-n,rվ@܄E4FeB>[SvɁqH ehGzycmNݶ}Aᅖhq|- ʻ .{IS㡏=M  bqo$LeC}Z5}õ5;I'g{:O% c<4il?#k]Hx;f EP\ӧ!);BDHrmmGk)$\*2ҵ's50,y su "Bcg-3OrViegб6?h3]+,g`LYګZo#(Pwr7hoR3d՞W=^fݍG[ @ m|y`5& x~H^`"׃Aa1_W-=L &O*_(yxc{6~-ۃTtX`ҡ.Izg`?>ޯNbhv@+!]oL݅̃˜!g~]>?HǨhElUۊݐ־%rg=`:5A垲Ȅyջ #Iw+hs_iX2%ȫpM޶,8/Jz_evMCUg^c1g^.OucY1^"|8u! Vx* 8)3 b}8/ BǏ$(ō(w $EQ`]ɷh|NS U_Xȯau$_S}ޏrϹ~XTK’&zEM^Td#{@yΛR5/;Ĥ|ӊO:̄ӎgb$aJ!_U^1?TI~Ŭn<$ |Mi3OQ}WZYƨ; + 6龌 w$#b=ȓvyx5[у0AWjESlcN5u2C/z.xg~мM۫z b:1UhfzHVE;'HW{b#fN&ϘŦ^REdqbK,f0b#kFK4RݪXN <C>d,$>$OᯆPRlySQg^20V>xb.}]s0XLqXԑvl7jz^59h6u2q9\Byd}L|Б uйqFƴ4xCЏc^HѠZrJ ]{ 4 f'lŒ e (qvklo<#"M o%i&{^EfA;oR}f?Sk[& ݿ>Ǹ9'$pJ=nM,ڗEGk_͸p*tOn*3+28?Ԅ]7^Oi@*0O+\onFKZݛфpeZV8dpy>B?\ԈgF~|0+MqRTKCvM`T7C#Zicq}qMG}JJ5*o'E,$awY[,OS\%5;ԧUh3gfs}1b-6u {l{$wc6ً'Yl$ DCMm{%"ىhw{'S|֝*J$_o="& ;a!t՚<ΓT=\v>J#d.W%Iv`i،wd&N@? ?rgƌ-+MWL56M SwYROr'WEx[{xAw="AD=5#̶0I7js@#,APq4G+쵡V5L97;yֲ\:( qٗLqRk,c%1:PL6TOZŸz}3bGQ,Hkkv*ag X͗̚vil\fex;4â3$* ZO3QQ2iR#[ R6Q7ZFe}JJK/zL+R F޷o묪ER=] u6c7o;khVm>;C~nbNÈ<ԦȉOcTN Tsʨہ}yYMci8v+}EGv2jT`I֥Z2B͐ViXfdћؗ67RY_SU V endstream endobj 79 0 obj << /Length1 1398 /Length2 6731 /Length3 0 /Length 7687 /Filter /FlateDecode >> stream xڍt46!0Dw D'!HD Ah]Q{ Eo$yy}kz}{_Ƭoħ"(>PI$CQ0_j)EA u`ԵA@H\JP($((/GR :u8pEB]Peur:pA⼿Á $ Q.`|Srz#β\@o(h _u?؀.P?z#0q w ŁF@=7^_wNWDP` NP͏Ap_`:;U  uCy{@aFUJWW՟2 qv_?}GxpG_C8z  \U!(08JomR_Op:] :A`/:BP@{3wk5||$h)x=P5pW@MEBٜ>@>A  dׇCj?b5Nn_{οg.]5j!@JPT?Cwῲo T=af v|r':k :G[5Pk"(a_#Cqԇ\`P8DW_kj9<~:Г=+ebZAXgV!l9#4,x(d;>$Cd^1i&7c-NFS#52a ܫgAN\^XEadѣ,!G ?]ktR?4mvzaBrpe#}(EqWUbsY\7[2zjR*hT&3 72tKÁ%3[ ~?{YStBCyp;dvWޭaA پMu`^!Gƌv>hrLSVf(d"[5c*=1Nпr.ZU4m4%@[2 .gNBHceF8(:?ħ 0Ir]+k|PD[BL[6FFGc U9{{=a ( A ${I&$Xv%S]Qu213>[_Y}\ܾxmOM>2"Q_ձ&HjZuW&JX7*Q%}iG/;0Yͺo[֮x1[iԾy윲}!Npnўksx/YQV kW,´pR2͵hwq5Ruk(Y(e5NrGkqD (geW%SY6l Czb;iz 9ؗEiЦz" ahf<ҲŸ_q%jk!*nVBEѼՎkT \bW38wCJ=kRuz^߄W|3!5 wfmEz%N?Os~'['Gl]3Bt,BN ZU:Œt!wIgJ,(ܦb—mdb2|e@_bǵ3 <2ES;fojʕ;e9 )6$oSA7g5h㾥{`cAvՁWX ͛v9A rI>NMf?&;Q өꃽhMz)m߿h(1r:bux:݂#=!%Tkc9OJ格Eaί[ݟgQ;R=6α?{h96gNN3WGRGX_E @{$M zI6x8ƥÉoI2hgZǑoa^ʍ1:j⒬Kd1gy8L;J ^UrOF`yC7O/NA+29hf}|[xDr{-%-+(t|Г>E сSPy- ߳YFa%2?|X_>p;?h҂OԨwRнɧMOy!wv6bҙ"qU{twZQ3;b̧)jl쳁[b$]ћ!O'{ҷh9nH-p5))-WK9i~##1GN,wzؒg J~ҽ'~ø-xrA!]7z 4Su&ß8w*Yk!]nZfɱpzjɜEPgI6jwx&/7c0ck/zMŶ搯RVx~_qGÚ>t?TKBci6[}lu G%qcq ͱb"Eg8aU]YDRLV[d'Gr>zQ:HݓYx~4nWQ%fQKH=Uf}\K<$S5jѴ-ܶ.Q`_r`ٹjUr鼀SljƗ,j%N:\VVUc*cm=`Vo܎Sc=#o/(qA+C=-4$\hLݺ/wKh2 ^+(#a3 νx<$VUIopsv^wKj94`As9C-ݛ)oT^nsl=±ˬv|zDw:#bz$i؄͵RnԋLrBB漢6^Q{aԤb²"-Mƚmh(/TOS`cNޕB3阊oH8.tTBװGՆ^dF-u=0s&d7F>W|*SUKu\9z{Fx6Lx9۳yZ*?=S tYqB;K=}׆m-sb7f3Xu(-ZݱQtVx':kN ,n^jk$3GY|p(;x0g"NZj]JZx^Hj%цb X?Y.wLxGTPĚ觼@n%ݼ {)&'.Y<&^br`=ֲUckK}csZK]S$ wN<3Yz}νॸ 4V7:DY$S&+~wmCKǷe7 Y7jߕ(+G.t:~x, >{$gSna׋3T6 Rtgnoe֜4'n0g,gXp.šm'k&,y}036'}zoTŕH_UtG'AԎjڣ1s[ҩ"{MyܖH$JNvN5B'/sRoF kK4ή"V=:Z8NƹKC(Fl %R2hɑi i/s:IxɨG ОtkxK@;GG]LH zY͕QD՜~U;8ȡV{ý?䌥TWuo=h,)s3 iqQUrh|c;n eϲ#BsXÛJA+1]vwMjhT .60C_I/$Y!n I2 |YPeasr\vG~4TWiRDNxilǜT[,n5 akVLӪv.9n,&!%Xdi1O)Ŷis2UsTH'(|X=Sec2sZ`F!NDbWL 7,}R^P=%46\T1a}<.(] %KҢ =jZq{G>4eh)9M~P:@`,m(v/T.+]XrE3;| ]K-73{^xA*ܙU>˞iXJE-Wy)]oX{z+[T3,&\&le٥[N?Iq,a)wpzOI.r~YGbzlqms ?ñ%^mLaLuЋNgM]uxݟpLs ?49\j>K9z5IlNH٧]c^weiHQdv墜d>*؎Ojz$ORc>$岢D᫼Ziq(LA 'Q ^O#7+*;tōʱRI[zR'IWxwl-p$ e D;)SI]$OZc? R鎅 D'b1xĞ}Mgwd+?0v$oJ tztb`b%K`hhbx4]jBl>AkLH(;︠)9HJ^GArP|a%}>OOOG|=w06K:(ƭ3uM0,IkF|k(-Y/TrK[QW";)P?G\RY7 x׻ܰ*|[BFW#R3/K+tokS7虰ޚZ)F/L92ۅrsT?$%~^M EewB*6I*w@0z{z $ɍ(͌Z-V1id+ endstream endobj 81 0 obj << /Length1 2091 /Length2 12186 /Length3 0 /Length 13467 /Filter /FlateDecode >> stream xڍuXkJ7Hw %]0! ]tt ( " ]gǹf{ZϽw5$ 93S aFױ8h@nv`gH, Pj v(y8x\\œnNN݄2vVUvF/ vq@3dp t-[4# ځ >Qqbprgو3 -;d6@ Osh[;U`k8AP'g+Pw9m+?ps?޿9l\,}mv ; pmh[xZ9ZXB * ' ݁nv.wvw;]r4 qG]?G r휭b¡lRTGf899 rRrCsA4?w O XlDAc( ƜPr8y2 ѕPfRR`o7'%o /WEgk0@zo͞! Pn ~qf_._doMrY0ead(= uPCbU*B,k!l6;/b;w9;ohM^;G;gU`?:׉;@U߬@XYqBI./>8؝ ahE!~?HB8tAB?HaqAv!<&? hI4%%NNտ 4%z@9OLhjk;Oп<Ah ? ؂e BZSBO0h,g'e+ h_jQCC@v2/;b(79\[и= BTă.8 :(_9 ^9@)猡zn ڤ8OЙ?Kp n_o%D[E?Jy^={P;n}Q#v(#ͿL˕6WL$r`GŋS!=fU8qKG@)uŕ!(v$ hoU U}I.􇺂c0` }hTR[%#xUs}R|A3hO?- ;Gl;_uv~`ػ`-^POs$lx|I-;nTW7uaȴG 9*U'Pv4?xwnjĜvQ|E(yqɖcgǤ9f $ Xh:Jz{8' VtD7xuise  }9@Y9cv -Ya`ߔϞjqI.2Ɇ JqP*6:dlIӉy=wgJL.j,l^Si؀rFvjt`F%K1 cAX8Y",U|ւ;-?Cl\ i8a% &V#;1"ϡ?umI06"Fhl!,A a4҉Qp?>/)%i /aTO:y0ߚ֮bi)7&ChñNߚ:'~h`V+Ұݺ3$V3T2;;y8N)+/#pw}m!d!pO,wFalBrh$dRe22|=~ͻ4~FMsWXʽ/{ogjǕg4HAQpo3moߗ]2l6IԪ6>FI$Hҫ/(z`wP*n~38D}q-#JKuGOk~Le{[rBuӈ,7i/F.>7pƇ 2DP)iXe,~D!s7`E>H > ?-&7v9lh!: <5)AME*5NCž"׋8/#x ISt,q=뎃o)7r%kt>bQ/z>#b UѼXB|E{hB(Dy|hO"va#S}-ě$+` exWt..(ݼ'`n8;qiydz5Ƃx *[%9O zG8jRM{SNR>7"=^ J}t}+.:>:+bz˗-hpRb*GNdbХl_Oa3,cP}ןp-Gdi<_i^f _-g2 )Rsͅw^6"khHW*xpaڱtq֡ Q}+>*RDx=ӬH['N$R(>PNhVglҊlGʀnHX;v,i~Q@MNQ{F~BIXzR,H9=}D6 /w9*1K5~0U %фh]gK}dNC8)BNԤc oG``dqN:NK=jn&0+؏zwIu #|Gp:Uq=ga%VYQF%Z}sM*jD#ٲ-:ï瘳&v?JZ[<c~ԺaG4nv~U=,AygeݻGtѧG쀹t2a^~WU <.lYb!ݢ=3J7U6*- CC0O1_6 釻 KƓھ,Gʟuc{Bu#.201܍(6Էq^ 琢E&W*x)RY8vik;雓;>AIϜ7ڙp!N #Vݵo):/Bѭ^u\hy?}i8ڽU1K:GX]¡8ÔSWbrbh$L.?Q!8EckӐ'cw!40]"m8}rc6$ٜIJ|:NT1zN֍7ts%xJ%O#Y"@ڕc0۷}mSmU|t;O%_ky[Jy"g?al%TX.Eeo736zpd'@_C#UJºE?f?`˽Ds r k>bIV0vl[ւk3Wˊ®_+dۃ㼉8JԘneYeZܗ"G=͹,Ty +8\/X 65 I6d<hY^@(Zb1>YD($ /'n ه҈5yc̈́߸V9CjF̓ft(<G,k CȌ45JC?^0MB2* ~kHiڲ/ΏxwOT |FC/0*U:O= *U LT ,~F8De)lֵ+r/Iҟ"1y1k iȓ~L˧U7OTOj9~]dSL<.9[:wÃGdq~+n_iޏ)'8)XI}S0BrMz%4jm"&Qij~$-A̲z;wSSе.¼=%"B>TZV\wL?Ͳv /$'ዏIztE#Hٍs1 pmqz~THi yhHq@znK$"FT8Eq{J t .UYj%Y9l+G,gez?}㵅ve% Qlx3d <[I';)sz!rs1VACuW=6o5;j+k bew@iI #&I*z"\HpDo;_5E/Hv(Q."Iz\gNM6B< "Re4Ai6b龉먕m_b>]'|HJS$5yqy| %"|;f,kn"gs猚C.dZIp/tG=e HNj$4pHhEҲN1r}FQ{9O#:o,u V)8ZKr=7c쥛O=}_XVQϦ lVj:l%j?*7bw/] {=5dSUw$"LswT,&lZ5^q r'\1[1-?V!D Y$+|ybݯEmrNJIx d9MU)tpKⴛ[9S*. SL{'sf@2 9~ jA@BU,K[ zlI7N?/CW=?7}Q(_:RBdfԯNZc)Ⱦz3N'VޜK4lDG(Vų1YSq~dgec1Nlʖ_PGsQP"7[Os(@tUB1#I[XRN)NrUUH=~]Q,8{p>xɩ1Yi^q澝h)L qdP'Wx> a_eLJͧ;6Bkw6[ D{cLl9foӌǞUkP@K* ojsj]aL1BCY7G˃ѐϭQ PѾIu>]FL;eL%{[=w*uNLr|^vIfWxB۵2bˡuQݻS15qy|R&D=`۷0 Ǝ:EJ^ٵsz| WԌT{j3y S7QNd ?\ K6~ӆ(bauܓzl?9JU 4T;|g&8;,/Y"ٚRo7QkNSi}·H+Ky>l2/pw>᫅ҳ"*yLeT(s=S4t~a VP0~ h׈'T`E1kF~Wa'?p}yFW3 m1}}U[aU(WOX"~zaIRLO;/;e~rI~iBʿ.RLc[E}AiM]"+%2ٛʶR=0~tpT¸?y5xjxXJOFvL{ VQyŅeXV감2>aŏԥҭ$QBt"d~CWEM2wED4K=K ~[ر",z#hy{ _ )zNr$|ߊ1!17WTٵ6xzyB]T.F؃iRH[h6/_K'T}fBqTRbw{Ȥ0i.%i$UB%$u|lײR1$;~l@1'4n|O%z<<)c3ڧ."$itVBi{Q6("ߘLoTxx6/|k*N2 vH#[Lsm͔ѠN˚-9A`* :ï>a$l07OvL=(}1:"{m|,Oo~/ tSCHR_ifoy-xvQW+[ɮ {)w])ĻSkGOmC,h폔j|WDWk(E{B*S*igeņ{broֳZCW'jbR{vnuMf5s6Yޡ-CBrEp9MnH bNCQR'a Y7["M`R"/v }`2Qk_zgPi(dt Pt`ؗ,o޲ϟ=8)!ղ"|WSh;UJyx'ϬӍeͮg.\E9 - [8cs }#UF[•)Tܫ@ޏ/넅Rfb pKWX2" _tC5u4 ߿H97P~$N~\]|V\؁Ğ& 6y-k#L-Oe! };LY v3vDvDAQy"$񥟎CDQپ*97;98>˗^FxCkFn5wx))]d64*HMt+y0éObٔ.'I^۹$;#roܿB(_s)y7X#-|Skg!CJbټ9*;!xk=ErNJ]CS~b2_]IBHta$ `O< c"7.|y`Y `v_4t[w?oDÞ?R晾.As7TfNR!VC̱5њ62D/Yߏlx.38$:s7fXzL&12? }\.!Q/UK_ Z :c J`AÇMqN*C@U3DY4uGo~J\X疐r9ԾdtX}LZb YfkGd}#Kn+c 90rQEEOLܓOi4?"p3.X*)~[@-2wEwʕ2< qUxwAް|i('fZ#j ~AǬpEXoXV"k6캎B'ӎ_ԝ"7"*nQdۿHl`,;hN7vAէv%$ /"U[qcVB$i{S}B\(/Q,:T֜[@\6H=0joڼ]&ӷ+\^[R'W.f3Ei,P.6僓r eH:bH'w!ZSt+®.J\ZO T ?Naxmfۉ-7b@&ut ,75v9r2^>ϯ2nX؍$&-ue$ȋ|d=^>b]7G~&} s%Gme %ibOk{ǟpU(S4]*a#^vkV⽙ų[^K|wGh2G7ߘ 5#'n3^x&_[Qs2g  0?h_NBsr8{^w&ؿM`.1lA2tHDCƊ/Ҡ,B'n=`uQM80k[( g "z\~pԌ\{/ހ1%#v7[;CLd?ԖZJK>ΒWl|mPWd޿~uc'w=+PI^4Ľ.|Q@P'#KW? lmt(i'K)۽*9S~ PMÆo7H p YVRY4JWQ]Mi&ڠ eEOTU~V!T|+8}b(>,q* 3 7\ d6j )BY+y7øUbrHuJrPֳ\z3r*ttyZEܢf4.va .{v]&!QN~_w񊝺jUY&,4~p*8Hv)$T "w>gpXY^eJ50d n|D')`FpAκ9Zn)b)/샨 Bփ͂i6,GGF = C  ic)RdDPEK `("/t* J_-t%ؖ҇Xq_JAfXctK7rb-\6,mm&ؠ`2J(ٛ}xˁ8ۥݦwK49)]4oSdp zǾCN&m}YAJ6r?;Y3.J4;w-Ŭħ2&[UY^ow~ylxPbt>v޳AIOk>l2e'*¡kڿ[!"m||zͦ-lԫ64H3M Լr6z&BS}>T]k~ި=ო5fZ~ߴ)׬_R4q%L2̏K"W>Rd/0xGk髂.yZ,o0Jÿ BUb8tKj諳3NJY)L!#][k0KO^x|>̬A*Y,O}AO+<?\ '-sULuưg%!?<蛍u'L^# bvGr !|)bpئU9e&ǩαw#{b[q 'hwг7٫FDtj ­HbC(YX a:+NJ$ճDb]P}\Uz9{=#qgYysˑ"jWcEmUPUJ[_u2# ~nKW 5 w}/5O}~u//F`rwypW ̧[ I(%K!3ցA[D,7K״ d\quJ72):q*0szu3#g| \*!5qS^w{/i) AC#w`|{O/y9}ukXyQ6lzSxyz?.o:EC. bH}&%z\؉)+V3[Eq@;^Ό\T;CCQBUatw[y _2 !uP*r#%]X̙ʪ+EBI!fU| cO΁B<۰>X3ҝ ʇ4K~8ʠP!G!0sLR IWe/ti/ՉfD>OЏ?֯C߽{ +)/!~ Uq4)**2 f4a/-Q*>Q~'uJr>Pgگ!*o gO3v/vXۯ\y_#]p=Vh>g9-$*RY/-IOb4̌r5:D >LT0pR @SzP[LǏP=Qr}ϳLk KOU;z`xY*@. o; բO4ZiC;%8+QiE*i;aXH=ZS5tjCa47,ˤ g&kr 6U*⩐$,9<6T޵,@$%uAJ8F>EKn i_Hi9`G KmwjY|ցz(5#CҔE]8(]{0~=eљjyvNJryƴ- ?E|.8\E|gVGVjK}1!9pc`m,'/FW\fbt1-9O3[>TΫk#Nςw >#+*A%?*]Ɛ%&ʍ %׀PK5S%@V>/~f?t>~@^nh4rI?9PoEdD.mnO%]GCK0%U^;qt\Id>E endstream endobj 83 0 obj << /Length1 2318 /Length2 12500 /Length3 0 /Length 13844 /Filter /FlateDecode >> stream xڍT6t#0tw 54Ht7HIw7HIwwJ{_k<~gAE$j6J휙ؘYlVVfVVv$**5 ?r$* l#"0vʃ2.667??++?`G~+  KgH|КxrAvycgK-$ @l :WZAKgg{~777fc['f0# l P:]f_-mƌDP9P;; hqq3: rE{r0!ollj 7sYA6@{gF/Cc'0dcl1tc2?9:읝@6zdB8h> #»;?õyabϢnrpJKc!Y\ԒW5w{_J_bH^`{9 d 8;sZ:Mfxp"t#]D<-JQk,i[%y\zv,]R9%,||JHgWՔ pƮ4'XH{I_M9 F+J&ʓ>7/62(JW."J>FTP ăT=V[#27؟׆u Inbg'LZ~06NQ?od^hfk^[ 2S,?mqVxZ?Hſ\;~sGraax(%'ydఛo[NBKvuS3V@n:;KtSvl@c!,AR9H+!lIް/ ԃ;HK{nİI&ϫ3X nqj4Q(o3XsYV>.?־П嚗WQ3HA-zjF0awh%x$8X>Ge"\VWd *__|Y<0C>wtZ4ް;!Ě]"T1vl]0k%-eP"%OAG`m:pc|@I\%3W9HQg<_lڱ r"1e]:!&!v-M[ yX/DA)Ȥ&Iuvc|JIf_jĆeSfyRCr`߮c^G,ÿkP}9g0:9ܙ᥹l&`m l}w&@7JmOR-|]-Φ'e#Wr['MކZ qG%Y^KE%21:8rl{0R Qx}۾rmt`%wn󏑢0HQ`Nn6W9"VO7+Y|vMD%Є:tX=8Sae w{.* S @ ]$X/AeGgQNooccq#4?9 _i^z2q4hps1q8(7_=IUaO-ڞɋ.݈h'" W5E+){Nf^u7o*)XIF)'lyqLvuƔ-]TyB:Vh&~7`cGg[D՚0VvAcЗё,hkvGA[wjy#ӈWǕq_z wZ6{ @^#Gn9C zFnY^{h #YbHq.Z\J48hv+͞e6\lq+DF%@G_ sGR#@sh'UxiJċlѪ ί8S;c0 ; tOra1aR@ՍB>%WS޹mtw{[bi6߁Ỹ= ?{vUHqg7PKp|̓F%˼*zx?|}AR A5xyT)qxY[?M-6Ứ k>+Α^H7JSʬ(Yn߻};Q^.R.e 2$lXkI/sYh*K:_?8.2=WD;yNHv5z*޼ZϤOv0(\:/F xG℣}W탌OjmHx ZKdgt5dFM/akTRܧ_l78^chI}Cj\n)0q?U9\% ;(ȅJ-*o9LYn%3o #%UϪ_fvXNvxI1_s~{w=pGZSqn̰1R!M)_U>)㷋|ly+6$Ʊyx^xv(h~z:D=7pJv~C:}0QUw8B v`iq.>[L :s;ad@C­GQrg:Q0\(yUǓ}wb˥Q}ZLm;݋]&ĶY H0gkuW$71aOur3Cpg &IJ[#uEE;2&Iw啴6uep?_ҍ6T5>H#shL2@WBha \V`1Bjl:=lUQ6Vtb;^= I@Je1_qHGA o,c&Q^qJfXӏoG|BuQɄc~ۤ&p P]8jVg{a,#z<ζf tFܖeHFo??FIU3C}$AqnhmbMA~zøpNP;CR4eΔ ,6ݘr' 9' ų ]mVzwtAr61ϸ}߅kOb7vp|%:9\ (_bq1قA/q]) |,mM[Ykck>ƈ-I}DZ=_3 S33%=$,#@#uFTf==mo{fI}чt7eQ-গtc (~cii+|"qhm"~z:|IMBv.q#1ln"PJyFvW.Y'% #gyH"Y33qRH?!kQӪ}C:'l `x09kDV+9sY7L<=̍) &CYtd@Si:F W}"5=9J1[BBs G`2vخ*q8L1o0n9"ˤ(of9z{qL:nBHD-n 0e#IRGg[CzHVXPJ&!.uw3ܠߡ05uw v}PmJ?Úrmn!݃$WVQ&K):q6=EëM k$/G|Mv~ЎQL/*RGbUo|13/Y>%K-ftGZGw?EߠM HJ?@^g]s:&)D#b̭6:7bBX7:s57hklKcjb3E`jXTazU:S`'/Y밐 PYB((~D4%TkWc[S3vV+ ޽:;\SS (=P=aָ#먍qiq&̃$8Nk]cq6+j]S_|F|pplٺ0"laT\u D)zĂ5#t~6@$0>wOxkąQ4?js㢧b,N04bp&`w0ߝ U40{1֮Y:ᐃH4:]3,BT:Oa3Hn؏-col*#86o{+~Rz|&jYj;wlHcf|6:5C5@ZdWW+Kx`~6vѠDZ/ԲA1Iz|}pt7(|, a!~mXu'1oN$7Cu>"'Ifl.<Qv萐 + "}-Ts zEi‘@M5˗m=@FD9! ]s(u[%LJoJ5޺ WI"WʹDΕ;#)RȄQՌ -?1B2=לEHQP >wgrwsv%dI>h:TbR =)ٶ!* \ngP gh`+Qip#b4dK∨+c˜ZF ]*2L%-7D&„&OxbGx}Vt);P1F?^6*D|TUf}.·VE1-a@ocwv7Y\d|e`} cmy JU~oIlj}쇶̀kwq.߿q}3;*J"İ)󮠧ML3Hcm!}v/BQL7'_V|1~c.E o| ,/^2RUz)rp "aG!aV9ASfP6M;dW4{fXxa# M|Zʗ['Yrt5 K'z~ L ҝsng.ʹ,yڜRt׈] SQ/jtR)l$/~ =@N U+m$ ?[ϥ.&{4FikiP0}Z~='`qBdu&PT:$Pxb^]ew^OG}xLf IP_5vP o^i1:δإ\Faz9_%9 җLPr͎kJ3G507$ (vb}uY_#j""2->iΠ>A@{}VP2W p/P g舔r٧qW1aɠ`)n"' \,ԇ-㕧VB룼Wy]U !m,Q3/\)/4b/V׸O;pfXx=jDkVgvmS8-xD~XU(dwAMR%'R qp Òxs]mă}汛N0|"S\#EښwTt\7=R~yh=/ʛ_J{=ڔ,K~A/id/3Ӂ{脋@@`};&WF,LfOSA0~M-"v6N#^Pwu`)xE%T˗#(P֯Px,Q^A_.JQT+#*.9(-g[/H S fG76h38{qVΘ1=f* Ya7I2aQ>5YDPHwD6$ nK/J[RX&RC$b;*ى'$mu NOAz7FD=΁J'>_Uy'NȌo a"bi^F69M,icH98 ;l舲l#VҖ`Rlc-A$%rN]~m`WLdf6iI:j]33]cqJ[⊤ܹ'6a o ;mgbW|_$T|FP`Q_~H-[lade?߀C<ё> ȵ:Or|R AiqEwzMˁз5cjea9"n߹П_(^w&rhT\7 )_q%~߀-TiǃyCumNjmchy^_Q2$gL5^`R״iUt:+E4BX}V,gT eU~$r';%ĵd+H.R(.`=͗X~LmxV:V}Vp=o#O Z*.TC`KTkXէߗ\_w.ICO L=[\mbfZ*!ŬCG;7pf}׬>P":,;\l*V_(m) ?0AŶ!1a;Dle#0ؽ_sďKaMK+E+0p =WXb.%S졣&GڑUЦ[{Aۢ"Jz{f n8ܛXvklg~O;ܧwJTCjXm0O2pۄ8?ʚ皌H~ JN_ ,Q)6I#kԗ=ŐI;ܭ57qvIn{8D\H Hysh!8\r8$w%JMV,I{|(毛إ-mG5p'Dpzbw@zʥ8d74scOׇme9B3>&7x?/ 'I<<W,3:kC9Mx@ߵɿ 0:͚`q" |CzgeÛN*QźL_CiS<#}%f n[.bm0u&*oezJ0V6@j|tvb<]̫́ &3 B;ݩ]+}ΰ򈻴t>c]OUY_4RHB{U FY%H’s!Q_?U\~QN R4Ƭ!?4c˹֕~Y:˝Igrcc+l01{N6Px93v0 (݇u pD.Tb4XP/7w a]Shy;YS>u7ewQz]k~W1YMtMXr~%r>ú6iJWKRޘ<="cz^aAd&s胿~M>5-UQTt4C4K2D#UO` :R~_rƂ:UVq-iҝ"F\g`~f} Ə. Lj/(Q6Fbb2N޷3 n{:smC=#Iw C4ld7eLy1m4/4֚ei:#숌6]#˦z5c;Hg^8u=? ,?ڴ﷛w^Ň}1}(N$TR !EqK8|ƴfY+[ӊ M(% 2I7<ҬT&Q};1hB0P$oȬl;'AIkw ڴ$[&$ݡ2߹(_hJaMsV,F:G΅;(=}-[-{ƪh")4a5z!}6/2Ģ>/VTV8,5sTr ߐ];Kd)17iIG]hnE2D*$O$ )YD54XD)=L@[2Z1O'x1o"Qȹ[ OazxXO%Lm>ĚH!.@`k! "PYwSS$`kڐVWbQNuVEoˆ2noVWų9P0yq;'C+qٹ xx1;٥]%?O2S93!z_ŋʶ&?\ m y‰īp'b> stream xڍT. ŊoqwR ^wBw+nŋ(7{>ֽ+k%ywfgބ^[[fVA|<@1?q!'8`78/@A$Q;|Bb|b@ &y@l<U axAsf# vX <ЃYC`G \xy===y@p;`7 wM3xp r'5 GCmn=u 'YOxNWD kk  l!N`: Am~ANp28?Jet dv > A8dGfT G̫)'$W0//?_ *,;6WBU0"=_w.MR`?:7 o|j#O俳_u);9I g_ p%Ѐ!W?7Wlqw_TB. AB/6am^?iN(X[|@`vDp( Pk5@8@|}{!c/@lan8WOK%@[Ox[w6ex^[||h?t$E_82Eֿ`d=$G· /XɏLO2$vyZ!?4?00 l3;v n\Zi 5 DLګc+}s)'Hў)zIqp5eږ=Y9е&{ĝw}fQڍX&}#.Yi, p OBDd>4gZA%v3IuWy>r R){mZbofwWIZGPy *}@|LpY ذӑenfoL&X=vd޻p_RWWi OOxr4+ׄjjExSo H=G7 QblՂHHguÅVdiRgaTboSa5OMТ矶P_n &[^)T5lTI> 0{a}Æ/o!FEiڦw{Fk/gEJ>q8*9+/''#DvQ3SZ1Q NK K}y5n A) ^7[~ԧB(nś 2m#X97-en/2t.Cg; qQ"~%Fmr?'x>= ql!s3{#U k F@UY1~C";B G}Xr;a{,]lIj391LAڇW hBMd{)htIx)]x_U6h*Uըz1fxw2aԧN遠Sy3x߬rC4)-xQXzѿj~cy}1W6Lp۲eCdڕe} `!ޝk@;1"_ {;!wF8FNGL ؽݻM^`hh\ M-5YzkxX** i;oT#`dlT8IuZ3_՛-i/\5D7>xƻB E!v(.AJ]B+V.&!QRX+K<'XwM!u>`JBZW(ђUշiT o^f< AP_hIeoWvBR#Fџ̃G>Gv?uPCn>Bgcܗyk:JM%/f*,d`EUX,fe)ry%GAҘ.G.?QOν(5Ȓ^y֖ w4V_뗈f8a͠a 3{;zb>RH=K/끪h8}x 9 P>%#%>cԹa)({[T֕4Jس2*ܖŽ/p;$G;tA*F &/XO16ܰ91, E b؊+2ͷMMr<]xžP2}wN[&(N2#}+ߟc%3t`#qEKO V:ԺiR~ ;E^îY+,\'k\ o54[Iup yԈi rBe}" "ȸitFYqwb vTAxӇ Q'`.C0&Ahn.s 1ۍ ˜vfg^S6 w6Y:N|Yc8mצHtr(G<ᡳ)nCSWux7ܜG!ӤoB̒Bt/w.>d,._wKzm!<@͞G_n띯ypճw(eӟ<&I5H>)7L6=?g$ι;M͡F>1_1tUBmڙro~73E5ޏ 6`x9G*?RkgvWSc2P)K2nq{ӽmõ; _tRp\Y5* ƅŎ'ǖϖH|*ʯ@@j9CɈ]}|K+!4oNlx7I >20<>+z.]ao%k xv]dUfc^:1P`e`RT'1cƶ)~mm,4ǿq+Ad:dUr COrv#((3֡.k#*5+kY$i Y"/"kEdO].s?/Vxc;O(]5wdnW0&OD4dޒnoDPm7xj97@<nE\.N(1>3 `i8=uY ud. &hfJ6urp>C|Gfbc<)x|n9 ek%m#M*,j,ᵋ\zt#-I߼kZGn wd4`*hٞkȕH XfX0czKᩙɐ&MC Ad(nW#dzL=J,^ycd&,]oQf`o"I #bPўšzmI{e;qjЊ4!2  ~n/Mb}taq#AMkBHk!T*.QR@ "~g֝|\Y8<1풽wK "Df*jŊ|_R%De&h`0[X5]gP;&.8Wm~+oy1>UJS_wC sx%=߻m2,R ?4Zqq zEqsjq  |YzXX?n=V1R풇ߵ_hWVQw`= z+/*4n]'_w j'}GJ̣]L&zSqW3GU¾G4aZ[Zw, ]u1bGSl r)p85bO2̮K= 1Qxfe;JF]._ƋD[ Dii O NPf]&b;$G$a {;Cy/Hot-`ך "el=uє6cĶ]"hݣEOJč +6Ք"=TR4\uOY-P 6&vz)̡ࣀ"Ba<!,֕d/w:8頟vQG?gu!VmM5VLC 6m`9|l~Ϩ!-4iޗDlnk5ly\(j@X>3~\zXۿuc ?|7H:0Ùww4KQmì H(awԃ&19:R#FG9uCh깭(ǹUroU\ɏ%݆y` %z~q7M2qMHP~ogL:(T ݟȖDT<3XOJ0#qXt"dLʺko~tw[/?VE?  \[{xF}8y c!7tA* {[/ Sn$4OCbqB)4bN"oHӻ}i`SC7U$63cmDe5LDf`#rƍߪr2h9(U~LEƖ#!VM'oyn{ :,(5V[1iĴGP^]wv+_Fbe" q<@ë_?-B:lHIPm=Kg,[!z|,*L-鎍1GC8p$?b^ukPaIH+ޝ'Og.9eigYѻʹ{7WOvF9N?檶%aay>F$?+IW~3Է:C mm Ivjg"Ju^Cѡ}j7G Yj>R+Mz1; ,'j34쐚Z/hgΫxh$`FU?^ ez*sK_Wn곂 ̉tԠuΎ~޳<^;M\EgosGÛ0-rxw.$ߩǞԩ!R| *q!GuQ ==tuUn9 c 0S珡:㪲r5čobɞI\S\g9uLH9L? oߝ 5mҡԕR?@j%6>wjud w,X U/'>@ome"ǏeX/ƶ  >'`=+R( |܍gcW4e>cnn!2'>fNArCv(`D2TtASYJ ^M iM9n^{|8P:,iங{9j`_nRrIJ~^ ( gp!FNc617ޘK ;]^QԾYMᥙ,?ШFM0Pu餡z$~ t&;b!Iz:]IZx.~ jh}VÆHОOG| Wk*2 D_Md# E\jʔ@֠5E}+.\t|ʷfӗ5/Hp$#ݪ` UJ"y[4a7Y2'XzKU:1cˀ+{wg!7w?RΦ~.գb?<|(v2;W݋3۵ƒKD 'UCZzvv5Yq5o^ӏi&k7]4 1_F/OT& DR\#Pwz?$4BH*kds,A(`o,CAc+ur\ygrwveBx1)"mOݙGl_p$W߶It.Qt}zJvZ!vF)c @'RuV~{ Kk4+vkSĊWy{mhN>4j_ocʴ/ĂV{f6jzdP$C7c2pHMQj^'^W]d:% 3Hvc/(Rxsdfk$QU /+%q ]|kmv i^u2εu0ړ; |8*5 zq/[F!Q$DDNwiL)K!=|@4XwQ&ђG[.=*?Na/LG})hӝz}hh-zjWM+VZ@N Ȁ ,4+*9k`{ v**A j34D!I;ذ } 3=J$lq?7&,(P|LםFrQ֯?}I|lt*W=>.&X<Y 6Q:&jTQm͹w71U]I\Ɨ~ χ^62 gVy~x>tQ8aMzewIC# |23}P#|bWڼ8BnB\yScb5k'0'_dhD@\Ufv+0pJR)ص;wP)_kT9*04V/H%@"42Sr<)4?ď2{,fφ+8ji5 a(|XK;8@?ywocnE/nGl{88i~|}AUT:ʸA^}Zil۞uڽC!-;um,,+`+lv)X~{m'&5Q2u*uopaŌ'Wwq1GύKU,Jg[b4rHZ)2]Z,\3O< EdPqvLU ]3_fٓ}'\0џ-˾`Ԋ$QB'd=uQ Ô 2_}H z` 3YK{|%qb&+.:"h+f'Q+".b0\P^\Њ q1fuqQp U@|/ R!.Tdhj.jn7rH aKNdWg *cV-`)%NAP=&lKmfv͍ݐ':v{TlX_sEfarS`"s#泻G% ̏9'CP?T@ endstream endobj 87 0 obj << /Length1 1593 /Length2 7770 /Length3 0 /Length 8802 /Filter /FlateDecode >> stream xڍT6,"94twwI0H " ҍtt Hw#- s_֬53ώ{~i5u8V`y- Q y8a02B08$G lZ"ՠNeW ssqs  d- 5N2 `:{ vs `BBR`dPD؁OY:t _̢v0;# gaCvm0 s[~ Pt'#@ˡA[{vߧ:Ya:J g_ ٿ N-A '`q4U9v@K8>`iutKÿ`gq#/19Y@N8Ưd!00~\_dqՆ3$w̽ _-]`ׯt=_|67 @\:akB0e7mxp¬Nb.)=uCi5[SZp<hZB.T%'(@jOnK`7:^`:7;OX:ߊ]~ -!G qjUpP}_:W ay RN$.[kB ]צ9@P8rs~@^]#@P_k` Yzbpkx`2pq:A)|6PƯ;p)2FB. :.? y\v@>xxg̰? ? gv޷@0[#~`0cv yUe;ն7=|,o;Uqi Rҡ$͙cS>#&iKr=W`jk(@R:Q1xj~6*;|Y^E ot~)A{⒋J!4'&LQyB }fǥ2ɝ.pcNDŽl4H;'N'5铆Yy.R5[xꕩ%lô)~miev+K%:˺Qsq5Yx:)=q-ͷ\: moY3tY ֊e`|l4j6Tλ@1GAlzB+]aܛYm{эGQ5Qe BTfL F:)Y^lSjtVaqԘ1;^}JOVIe]A<-4yTNq6tSs=ZT;DVR}tUeH>8Z`=b"J&/𱈤 yl|KM:;j}% 4jt-Bش.,47njdgAwޡX?9f5)hO;Ue71rpS6Z;e7b?DI6,xm.*m TڬJ AEzhƨs+Ƽ@> ć=ZL꽒C$"oBt}CM9oC—$XTK߯ `tR]F":#yUJԳk]Hh0I,Bv2^\Tㆴ8.qơy.% 0hX6-eI 5ż:' ƫ8|ÔЇMu,:5A(e' O:_P\#q5Wͱ,3s%~ᄃq9]ʃ[gb b:dDmxMy}1表}$;ÂBSJk.۴v 懱XJ=j6ۆ{ |%URwRgV!C-xV[_xdɣp(6ƇrKx^^gWG?fy%*,4Zt&|,4LҊ;?̸P7sE$H* ŨKdV`*9f:i1wJ2uDqb>"vppmqndz3p1&Fm}ѧxeNFfl.&&KE6Ji@)\@vCn{{P{E+"%^OpV2 β{|wBܫ$?FEȾ[1?ŖZ(vXleݪ:"0'{n G+[+GՇ^ MŒh0Hk`E Y꾎/⨡ Ne )\v8ɱ8~CC/f$ aPDpupe|lv o']A%IT5 k>YлH>|)F.VWI V%,F|LCUKQ^ 4{%:tOdϧg;Qvڎ]*`,KzlъROL-]6KU`K%T!g݉$K+Yo?}b n1%]\AVͻ%XsI,;Vx'L5Ϧ]>9hhɀ?g"@zN y&e1йX4UZY/^%x P^ɌI6c\12 <&2=vgaer*iqZ ێ8ZF %Dn 7UPh|g!J{36(iEM*4qQѸV);;=nՕڍ*SzhMa:# r2S~u8EǍoIG/鬋/IK5-ZP\#f‚wu3w-DbDT3y7Q!}l+Դ_r7 qQ&>Bflk3ɓ;w]yʓTamQ/$D_h&Ƥu(Mi6MT ]̧kt誼1t ழucoP,fJϳiP(eT_$C6'^̂,٘H1Drf>@ڭꌁ6:Τ#8>B_/[.֭'p?!Sr˻ ů#uya:b'O5H܈bР+V0¤씽9:_vJ3de~DDuIVŵ xhOd7$NBs,[Ev'%} %33%뇶K]kWWGg?FxD=AqtI koʔR ˴w9Sۯk7G@ɼ"Q\p򨓼0>Lu El?^#+[Ċl6Igs"E TpF8[BsM&;&#Qmڻ!VU _h}4%ΐ6fw1 =f8]^]9%k[vVT>|0Wa%(U]Ak.u5ʻ)*mS=+v9@SjU.\zJֲ'/(|2* _C*z}.Y}2gǞn)_%oBlN-ɡz"Ȭl=}\(CC[]˫sE2\Kiۯ$XȨ _7P N+wLbIkғwtLjYr+Z,yb j-HCSw(|9Hi%zмN1X ZU$=>9_cFw?7Ǿ8yaMʚ5G(2LuByx .A#}-s:\}f_sp.m$YpX9Ore\ I̋cbU o5v|qniR&\m6#6f%M[!/l,%;y{4oA}=$7Jٛ?%R+ CŰ1Y3U?63RLX_KcT_K;?J95Q Pk= OeN#á1θy*r&~72~>-?NQ>sQ?7jRNJ{ M4Qv$l9lIKߪ/u5fn{},U~qt$J%syP)CH[;MZҴLFw3o8II>d 1A)^;/G1{ Z1&F^oo_ l[-o~#kӇ+HVyy-qy<hߋx/V̕Sफ़ ~W>=JP/ E Xdl \]"}T2ӱ1a% FAÆ"5Z+abk]sR?h[> 5sou-ʻsÃ9HfNaBi*:mBRiq`s 7Gd@0+#~`JV匊*¯QޅɓyNxF"r?] (X>gH]w2S!IV#1+9at72unIi~ňIͧMs/oEر0;sixwESiAxy N lF92XWxQr XYfj>]*sgp'i$ gKQG(YnH#"p7;eٿ7X̵H͡j-X{: xbIHQtsNKO 'ۙ:R$rvl/ϋƔ!9gx%$X:V}"cqS7 ˈXZJklW7 C,Bа,҂@gszQ#; zB<Ue-WeF 5x_Wq wip}9/gPSZJ+ìdԇٞbT}} xja*$Vہ0ԕHPlb(3I-}kk:8B[UU7;qƑ,/I1lx\q9Jd[_zx{x(dא'ҚU_OCk?jM/iyYlb\/4@rDH؊K1.Gsjns \}!lpIDqUp]VbBn,f,(Ȝrrefx1XVa:!˚C=kTmV븣}VK'|Yi%NHtS5F)۟?CP2hk/r-E7WU(Go1 _˪YBy!<{%G0 MlNisvsTvwo0PNtzr)ݚE K虅w›6&fq?`F%4 o ^ٲ@PlRYM0$Yb 7ك S3?'be8nr(<ʨjC8ۊWަ' ^f?%7DjQ)!?yJ™K"n =NN>X RukY2>a\Qkaު`t 3UʢXІU|Qq%~E4*_U-+1H тIEVStJ^}]Rc+]W_ax\ۣl)~8X8)> stream xڍteX. "%H R3twww8#104HKwwK t4%%w{><3w}:R0K<ɍ ȨH fdԅ9@~{!pW(I vCdn @ a    dPk'@qf9{ávnJ `b H9BP+@ fqDT;t`VP`sss;rO@ {@!ljеҁٸy8"ܝ!p>@GI q7@+` u@ yUN7/7v Că=P%W` ]Pg7WNWï)~A ?Y(b8yo @m~b̥uq(Bl!n> (@\/+;_Et!9Ä9|a(?  ??A 5 ` :aΎ0Cl^ B fYÜh.M#Yi -- r|@($;&O'*9B784XYVR! )he$?v:xAh j0V8/KקFlÿG uzA5nVvoޯs:A4a_ gV̿\wI9'+}p76 B,5/-8`nb8? V\2L!PEpiF|." ,#!տ[kN.? *_ಁzaF`?? z>oo"u"u  G,bi`#7;!C/f!Zc? ?7(\nvp'G!7"ѡ_c#^ҿ!࿞m b=7 y6G'Ƙ(aCnbs,^IDy vuiK4 ޼4۶43ȟ|/)f RHTQ$m{u_0rhz[GlUJ!kn,t7Ξ096HSϤSmN|C?43*P#h!표,/Bۼ2LB_K"=9lB/ ,Nn/7Ԋ ;kMߑΕ;U WQiЎ oPď%Opy; UZ2kaMKPN[ۓI~W%2L{)لL(R}f1MEgk|u5Cf ( v킫A/ƪH0=gX#<3v$ LV:񭣾I=)B":ao]$N8pz?`oh梜,|oW /Pi{5-8a}s;1%\T[Yh2 h>r> Î.Wk(uN|;'l[!]|XY 'Y8W&M?qê4A3]FDVFuÀ&U&ڟ.>SXL~ A5(p]f ?Za tA>XN8YЧ024 !+-$@%^ӤTKotϊ<0 …uwJ#ܹ<[~öإ"GЉD59!ν4P]u<҃`Rnv-F 4!iQ> v;&/ɨ0"5" wNCKC߅Q/މЌ y"Q[H3h;7'aDU+r~3Fl-2O&v/uz|L?O-'l=7S'fWj}OVռP,SE^Ś`^UgC' ]$Hk4+& I ̐hF9i1?PZ+Uq$j~Ґv$me$9.dFmQ J2p /HW,&=P/c%ph84Ad۠F~k"$tpTyp(AzdP\[2˒mpt@}AE/vu!zIUd&OpHf.ָ}&uwx'N0(A G4V?ëgf5}ruePNU[c=oɽk`wyCU6WBs8W L*BG&AVdŪ>+lt罋w~ߪbn8'KUfB⠍SސI]b-jj3Q"$D(W7 M='S-'_+0W]DsYsh 2:r QqMyt471?U{9N:\(ꓗӧ=99eIQu697%ۓQT٦:F⿘\Y< v'w"Irg`UA1XכO%OAkT>R,r:eT(aG:rӍ2k״o ['ϴ 8nml6sv&ˌOiR3~ֳ9 T eiMƪ^ M+R;6Ş(N59/ۢB?A +=^΁&;I-~R\ _[?t&Xxvve0tNgVύoPhŏX#{oE\WԮV@c42tXl ,` f,EM8qBjeN(ayDdu#zg*ŇWoH2ccZF[;DUzOYўԸ)I1']X&bq^TL"m*{?!ww{ V>ВՅN0>湟36(.בfx |ᵣHg&+ ̡xui7Ci5O5x@)cloJ-k '%U-]D;4Djٞԑu-]!cAt2OVQh|yyq1!vs+'s+~+UZI{nLڽxJ}oll- BYSSPh#2zY[2=]uxʎ_=MYeZZu6˷dU1Rz✹xIbi"SM#C#R>LJ٠uAy@BU*`IJ[^6/ͻ%,VpEx:N<}2%]${Fn}ünwh|יDƱYJug? Rs!7Lo-G&+uֆ/~5VF +hLgûny$xd%KN[Zdc 4a*_EZS|5?] yAyDŗy,\Uҕ(wEt-鷲wM_6EJ S -e=M{Z6:CYb˗w"JY 7 #L+:'>v\€eTiýջ-/Iu֊-IM~xqe.- UmZO5h_l!x!^m~[+_kR>z?qG#j TT]K{. `ǁ쬒F.kfER7aAagY9ZgH\(\kD=؏啝 ibr Zf܆Z K$ ^K!Ϸ,lvˮolKTTGk)(A+ād?Mԁ>~E4,*y3&d9RjٕW9|4;pjJ{lRԡ,nu!LIc]1AW'w5aȢwS)jzc[9DdO;-(-Y388%ު_'<5֚?t)YaOf*Y$Ɨho],fzL =3c|/pKf&%Ә/ЮV3}bG%z'h./ۆSϟ=m jPj:4%Zʫ)Rgsd8]yQLd \!N~xd!nJg3gyFzqqFwMm" ^yFPPagF{tG"8xwbwvx<.hsɻj\a~(=%:1hx;86fj;iGaogwwSJ d=7Dg}$˺5gm*flG\53fPQ%|&s vםmƷRwbj5^l,=tj^v9؟<qd[ln8eNEm>!fdazw9-wǐEPT /B|chnWcZ,lZWc=aqhڿ;e\^SB{Jc({1-m@*|# B&.gMp\eNBai00Q >v F|O3KvnZh82J~4+r ;7ι|F}k|"1x["AjYLBB꒣X qA񧃢%\.Bb'5ZHoj&]#ZۙȳnMp Rk$5#!}M@Q 5n$Ezײmnʞ[*vS/x7DMF|x<`IđWШ3| {LjY ͍mU.?نT9 ;֨kx"ѓ[ LT:˛YHۢ)0^J{ڕde:N㻸V$#LK;e[sK0ߵJX~ ^̌e $|0)2*~@@ԍQ$!XjygK=,-5U3:mdZ hݓ ]|eFyr=X&k >L9`=5KF(uBT_Z$e;' ~\ ń5Oӕ[{E.ڃQT35N2(SN&"4r~̺ϖ_gU}dlc?|+YwHwWwWvP|s'֧0o4 &UǟNtZ’@ARd4GA驞&8_|7C q^P+ҋJ (ktjkLl1V56txoQ0-LzZy Zsu:1gNyZQIYB.K>b8+vf@df-PNd{`ȁK'."%Tdª> qڍˍW0iYz+sHfmNj@|du[m4eCg}c23l*&ל6dNj7o͏K Qx=d{g k@lC1'8UUpTܾKϟ=d ^2,R;MTc "=lq⎌XOl]BIj+ܤjcRzG ȶ45`IdTXuNZ; {d_|DzJncWZ(y*jQuFo_l8lA&zQfwKI/q[kF)12KlH+oW5,^\ E< a u? ѥ[Z9_Dh~_1 7 N_YbW?*LB(IZ>$byu "N M&UO$MD\Kͻ3x`>j鞵Ƭu!@ z]mkg&6L֙05ǫa$\' O$GPŃέ$SLeGfEWs;%_&a7MsWx HMQ{^hµ% \Ӂ O%)zduKhabGFS&_Vl:K^*^MD>|_$_tӭdDO@$X2Q5>0FK;-оZz8iq—EEzQB1m85MTRey&{ e (ҍݰG% nBCpvS ?B_9W JҶ]!VfBn\09rJg#)w'SONt-ܾń6k5BlǤQڢ<9p?{#jw˪S 7.u_sX5^:H=pO gGs3,m+ُGDrXHro`0B}1?NTsDYђZ#fA#ҮՌSK邯$:b}yl *ӫ8;I49VGlHVv?zG/Mv/zO B/V^%iR\ʦ J=Kݧ}Eulˁ-$eL:8 |'+`f2nZߨUK(mYze/YMYB۔ t-TE‡ira+ ƃܟ I"\ EUtO;?&I5O4v6 f+#Žri0-eqz*xX4\y +wKYy[S MtB@07'ܵ[i{P,;$7FeK?GbC)[AYl&@d3ByR3/748wdm,zFKXGlHS$rI/-KQ.8vQW"Qӗ+/8߆b/ GGzj  S<ɺ ^|av 4N KUo[PR^R͈ͭZ5\PXxA(e겫Ͳ&zX]ʒIf@0S~z^j-0yte[Rp~:6s82ՑAu[\'MeTdǤK9N£:{:||'\/CIBܺyR|b㎷mF\m4:C<^ u>͗d"ﱣɠ w+ŵ /Ŋgʼ4}KBrn;5Q`=. <?/(&\daaQ#ZIl- kLVSdWS$ȒTPV=RNݠVKߐ;5׋јy}UYj{!8]1;ewlk̯ϢpI}RBY\AkIתF!8a<4Y]q&opWSFԧEd`*A:W32O>T  Q9Gm,q{[y[Y/ĦRcs=_A2OʝG)aUjmۯif+4NvEdS{=; !kn$iC JFT\1;uïqnZ4Z3#4_-z:=!ISv>WEcE09=(٤q ~Ƴz*L#17g aap ŘػI~ =йDW+&|HePa8b͔sYFϬɃAͼui@w#z&iUK' #6n$!@Twںw3CgkY8d2,k7/q G-S޸216;.횏eAW^3]0d1>pX0 P#Mvm{EQ/[ǩ;0beg~L3$6QO;-"TZpשFÕEp&Qz}|*C?oʇ$J;ePPTǬ'Ӄ1Aѣ+?}\8M1?vC<-F'zU[Vde8Q#XOFhOu:A SXZ)ezrC %)4yCNV V`n۩3'>i=ݯz\ yrqFcK{Xp=׾'ñ!hi:5qRƽ ػ6uӪV.]'b:O5q#4PK$,?ton<#8D%Hݑ[ymyGv %%l`nʻ@6VQ?x#(z)§3r˷*Y >c+}Q6Lb˲<(e/pwfŵWi['w9jw=XzSFr!$)s'/BXJ=,[^4qSW. l?ÎYWڇ4do/1>n#rEHF%vtܲ\4IA\c.mG+g~jvϋS]W :#Y)(cM|[kK fɨ/L:T~5)>&7> |@ xGydq+{$AqlT53nli+A̼LW`,:V e+$J\lZc:QRmܙvȖW~$g_D~~&I՗O78UdsqlUUG؝wk`JvbF_sʒanQ &qbfQ4IQm&Ŀq#6][K蝪j\JaroP@*c{BEKcѠ*3+ꗁ<}wQ*ؾ>!5f[99%|m8T1:s:ߛĝgs>w/ 7L8׍t`zj;y0(Zfċ\ź"GaVJdo endstream endobj 91 0 obj << /Length1 1500 /Length2 7129 /Length3 0 /Length 8124 /Filter /FlateDecode >> stream xڍwTTm׶0RRCI Ғ0C %HHIJ)H# t#ݍt}OZ߷fs}}> 3 # Q A ^3cluu!ȹB(@@0,(  _D(Pf"P7fgD aED8e0a:*Bz W Vq{$Yӓɍj' !큺P7i޸0?nVP Oǿ  H5'; $ P A>_Df;zy4Ue9o, %" !!߉`.*p[P65{)? \z@ HA}ϒS,{I 2O JH(h Po!րܝ۫B %k.0F" j CBPv_Cn_7T_>ԘAn$n(ivAQS p׸ \]F!56PbpHTՠ u@_HDQ y`( J<@~ ? *U+j_ BcXCEHY 'J8^ʙ/W;sdB^FZdXܡYS,sngʛNqݎ:vm$甚a~ݝ$YZ|;4-R6vz}Y*'<=(PR}Ѩ ]Z`{QYoxE'K֢S'ɚi j񞥄_zg:hZ#T=WBD bwK f\e{lX+HotM(ozV ƀ 6޻X *{s1sΐn7F1 *Гûp)rZl"~6+oÐPF8[fۧ'[CjښoW_Fp|hqf8z%̘b8]ij-Ĝu݆%yddEFsv9 <sy^lx \o]"xy_8sE__? N)=$iM#DPL|3;x&]I:A/ lK_Eu+V"~H wٔ.{.^^Xe s&SGuI*,k}ih)Vz?PV\Lg 8`1&`54YlYܗT #P1F'S6bѵ[t-9􏨸8>7 $wxgS2귕YާRc+\$I.խ)k{3NvŎ%#w^IwUG!Dz@5*^ ta'j<G+Y'YHZ<$߼Ք rKANH5tqgIuYbBi릭rHl[@%kvܛM8e[)^= % 'D84B{qh}@7դYHCG-TI2 _I*Y . 7(g{ Isyuޞߘ>ĺK5IȐ HOuͰT` fiKp;0}$ vTV5>Il*A`|aKJJh>?}7O5P PJKMe+|dr zqqsfKVCAnc'C|}bi{~$-kןCN6nd(n25`VAa%G*&%ʣwnk5!ʼB́u-t몘:Dn8׍ K3<;Ng}P?zLD:xĚ<*Ye /=bt"5;Mp`C*ЖlZyU R>>ѪHD&32 Δhkqtpn74k[@vPH<g#ڄ{;za֏N-kF,b&#.I7##R# qא_r:kHG:l*/%k5ηLrt)>Dntk<^htZk9{d_(=B*Fu5[I7~Pܦ6zL4VTSCy $Rk#F^:.h44\L1x'#Eݺ{NKEjgngo~Nڠ%'jzQ$=@xI]s9Jd ~۵T=Ñ,c3sv_,5濵4p>G8TU#*B_A?ΌuQʂBKwWr0wVn%/,H776'ži{*%Tm7eKJO@)Wi8ztDO&}^2/+?XVmL$y"/pv)3 f"~mNv=]pUdj7CW[v7yϺct([NMo[3""}+hIWwN5 4B@\.iшA|X9|.tl[^[HP^GT1$T2\nǡt-HJ-vySyxJTaA͇E<-ZZYGP5G۪SS/$Ktgߟn~6x=^RgnDLf)N4~/]_>dw'4X 6}ۏIܡ[)B),d}I|{k@:+ kҼ.ORūpdGaC6s]tD3 pҺϏAu$<+3I5Ff-w nI߱2A HD[}4h MTMWA%&C{'&ҫݫdEYF%4YL& }7~Yz{~SV-@.衽 i-_vM;f;e`Sԡfq~4=hڎ`GKMa˽8 !R:t 5-c2lЫ4cWCdj/w%HKUtd]RˣYtxk聐vLiRVZl: '<Чhdžm<|sguH.Ed.K$~͛z*IOjkċBr᠇ 2-e>5__whgQĻBzghExatZ=Aak;\!KbEXZEkFH>V89&9y).V6L!諸6ƩO~b۞KܵQMy@s@QWT3U{n!̞7#/^~吥ɤev. 5Kvůd߸s`6êf9>u:?b(=>1R*4Hy:daǩMPV3^V˱_p֤a I# Jdef8_y|x.qdK͡XQLR|=MO"Zt<| ގx_&HZNOQEl^8`*rD,}|0Sn?ZuPŀ`ƱAh{kԯjо㛍=nM)c&BCYn*l>2 %?Slră#U Mgmd3@ai"|X"S=vs͢s2gG>Xe}+p.9B8u.z}kbn$ U$Mz"]% WYI>osDSOTLYTt`J+'H)Rr BNDyk֘R+,ϢCd?p3w]](~a( ~tFD28/ ONnN,Q#0k %NjMTEz8H֓|e+[a'/& & jvԌ0s+g=k¼wLK֑*ce{[BC/gzhNVheIa"-¹Kз 17sҐ.칓~Dz|4eGXN|=M=N`{%oEoU{mgu}v9zvr r}ސ2k\|@V'9+Y"#@غ Ŀޖ؋Uf8WO.2I{l̯ 6`)#Ϭ/\q1Ɋ~62RҘ쬹05XyG!LlyR c4BmTc7wY"E{ m l,- /K=OS~Vl^p/h?q$jCctalAGp|)JpX#oS\'2ٍ@GҮ>;O7}d/&8[9=h6b*Z'bW7% Wb+YsW|^n#N+0ݓpa_ќ=Qxt_4zFΡhH|tN ZML;'(7E蠷PX֔@1 $RK &a1!NN`pWV^w,Ƌ'#Z~25W$$kO@R3*KNTvq>c6 :|3WdzIK&ntec.76шЎZb;r 1/ްNIN<,|F6{}H\ ;_>5zVBԝ>1p>ErD,|Lh[Zfׄ()LX`8BPq#<^[\{‡A ="r:QؒΰCܛXЇ&1ZIki o1ĿG=3"!YkO{nXt*vN@U\\tG*|}rK&y?T9 + 4e52+XB5T2+98g_xه(s x!SC4н凉儕irR52EbB5VKp|$h-Foe]~w&X\ C&~u. d_^aؖ1`Cq%'.@ )7" K V嘦%ξlbΡ6s{_˔?zO/n4g3i#^ھP$5ɕsɎr i5{GBSc` B_Ǚ;w?]'3-4U{F6+9 Yb %]H&&,41 K2x!PiAIFFdcS7~~]"=z7lBzjp>cBdN0k⚡U`Vm!l*BXnqI ,_Q:k=|y OV#FLAzpVTV;BH"D4.۷p\N7h)~0rzw8{X[ǟ1ţJIٗ,NLz`| b;tzqăP (LwRًO; Jt4uK 3 /cܬ4W6%G/yucU UF)wJiwP$ϒV\fKKћ w3pq0G}E13kcid]dmO#҆B~\cc ,ݘIDžk-qˣL؋ʁ`H@;TI$c/[l=A~.C7:^_(-EǮQO'ʉOknIbgɟ8DLxS%]5)6d OS?si~ʩkֻ4>Xƈ/53$8M2yژE1nS_nВmW9;gY>%2 O%ίAS~3[$5adYy ײ endstream endobj 93 0 obj << /Length1 1379 /Length2 5902 /Length3 0 /Length 6848 /Filter /FlateDecode >> stream xڍxTT6"̀t "90 % H()] JZ߷f=繮=6;1#Re]cK! M(o;> EGm*(4PhyB"!1)!q)  J DxHT콠]F+#}=N(to\ n8p tQ`7tE= `A(qFܥݐ'9n>7 0#^`Gzn? Lȿ @`PDxtu@ gsBBJ'W"(w=psBN|P|{/= @{Cahj{C<( 54mV;*#pW*P0ツ@᎐_c8z ¡<*0hmN`@()&&*?}@΂ ;3#@(G{(Op:8BA( wv k> ;k4p῏XPLr*)!|’~I1 @HHH .. g{>#VA$jO\ g.=`׿( /BgWݑ' ۻAahz*Eo9/nD٣ՠwB3__v(R v4@//p AGC ~ 5Ϻp؄EFDBhU:}~ (G!nP'Ahߚ} 9H:exe"71յ$hQ3glGJv54#O *"y/} Y(@ao(};}frD9M? =J6d$¶L5z @r(='aɠG+wa>da[C [>$I 44|MPꈣa5܁"'Eڽb5~Z,#)ɹZ-H %s$VH,;3EEyT++Ŧb4t-ԝA_X`.5>1_Iӱhb鱸yZe ?n}1u`;dIMn=Gjƣ*מGtr''cR~ 0ɚh&B\hB:owR*B1xR3Vt`[*$w {ݶIr8Ƴ.zlWǩmKV9[)PadK^a${׭ ņ 磌2_Ovroh4]c; K Eە? PƘZ tyBϾY]H qn;r^HI@F̹!)Q!MmBU~)Tx. i߄k/QY=i%mRw?>e@^ 5* Ue [_EDw-kG*m8іWN#[I,gG, Tun7lִU 4}i)v9;ðһN%|qQ)=5 ,Kf+?ۇ) OS{ҘreGlUu=d֜M=etpH9};PhF/j$ӕ*RԼ4l^&/us]|Ob 765lkW!",k; $NX}_`ja/TL%Y1Lz><7lZ+ְ'3.E4O-l P'NU(K9I1 iFs7Vg>OE W'(J1{N~z 񏚴!Uq~&Y䟕>;xz`1) T>]Y|1B$ZFv}W}YU s0'+ԟ]1e=²Zbٿj_؞yxj3ĚTقl#nÝb/؞spqa*ӘP:q;8_Q$KLIt eWX?1uQAn-3=50P0!Jtd?Zh8_IWq̎Vsh_+ Tm9>m_m}-?Gyp*f:%ԏ-1mL2`_yD!vFAv+/iUF4 Յ@(wR(ܺC<+{hC7v}ƘXH66︇:T-l8rV~ok&x+!H`Mm$5]_xib:6GG]|̯yAcJ rn+4pn9r''+PCĎ-(ɹ,".\̛,_-l+6d6,p-N/1o_ač3o+~j /#HM\b&;}T\ԗJxr+Ew`o^朑juΎ\4Pn;bU $('<-ȷn*TNzUǵf6e5V& 7[(=Yy$BPMӛ^yD'yoZAx@[-րͱtZOעޮ.*nD5n 0LB|E1m5GeNôɧG ۳oI~$Zy%H=?3vd܀ĬBK9Ka>K^_z5s`*:GDB. ሳNNIU0%Q\xH轧Q_ ʕrl?9LFCmG z.=s/*^1c=w)j#b0_*aQRP񜯳)GMOHvFE(ܵXLVo03m7A3望ɡVQ~=#tHٺ!NccIբv$Y'<۵Ģ"%jN3 󔲶7s˫:8!f^}2u 7)8iPݝS9 <ˬ?HT=;Bg}x@`aѴr]jcYiPY7[<#8[8}1F\ OA znO?<`y20"2:m}'Εz6e'}nIyg@&J/&UQ:Z8ٸOˌEx]h<NV,G9M`25Hx暣e(@fuEAJ4QMpLc_N}LN;mfaMRƣۙrDc]"rZ~*z:,X%xt \"c/1Oc46zU. :(P>Y]"`4[rCY߫>AZ jI^)cg(~; 3}j9+aRV3G]jSض?fIS{pi'sIvㄸlXAG'r䡺ydlr ~s=ēv]ڨc_')c0dr W} [JUճOTWPSKN ٮ^R} ϕuTqXTe2bj0eK+;>_˼=I['DrSFJG @29/֕fscpȵe&-⮟j)iێNhvByFd2} /^ME铧j_M/ X_iGFVuL[vU\xPGzlFi'W\7d\Iq0_f)>+NiH5xf ڴJcп;lr*Z 3:y\ߩm+jB{p յ 5ZbkF+PLClݑHew*4q.q(R`u=aWH)SK\$/dkm,H{?WwfED~>1B94sRImuJ)wb, 4 XLw[TX֛/Rd,bܽIm|󕭍qPzlC؉W/q6__zxvP0ĠVh!Bc{Ik;_:gnfizo9r|Uq|V+5V1S:{mÙp -LՔ^ABzmeZL@`H(qHEo5iIKukFSdh߭O}&qʢN8}$lQO8cP\KXXi˅U 2Qrc=no9jNLF$đ΋%f$efo;NKjA9żO6,^*th3Ҿp9)x[CJͲFzv }a!V35],|ˋIpý[V9~)l`eYѧFv\ I}序7宒k|>l3]JWCzq, ^cIl?P(߱{ss!Fg̠ NJexގ6/hg[箄I{}n1Gy+9M&w߼a8Igj>Tfd7ݣUEGHz&w8e|񹏝1{[hreu%+p'~*8EoYk-h×tgu0s@--Jcvrmz[T|`3iRY]j97hc4TܐPTVnCga7_}oҪ,9W/,L'Yd5_=SkŦ _fZ#x^7$~5˚0M}dv[0U;zQyAշ̧Cc[޳?|-ӎwg\(\#mbf+i'0C/t7G1mvRa4ud'y3"\V{\,Tnƾ CFo}f0¸"k d#*j{oVUK5M,KR|3);"мYO0> stream xڍP\ w ָ;w. 4n݃ Ƚޫckε)HTDL@v ,̼Qy55f33#33+<5?rx G' ;[Y:21󻡼-@`eef23Α t03dlANvfy6p9Zm@gs{Fc5@?!͝y6Nvf47 gs 2AMfnB  -AN..& G{v@d_􀿛`adoda3haak0%ݝ@[? Nv@W5ҁ e-읝,G6ۚ؀lOdw?&.L. imE@fffn6Vr76g#=O%w>^vw  Spvtx[`ba 0Y] 2 ;@}X|>a&vyLjRtS';w; o%USW]OOAX vs P3_,O3G1IX[G}n]w@}lŕX_3}DlͬH ' wX=)9YqX}oSzߝ(nklgǒrp@xIbxo !019L8RN?7IῈ V9<&"vw.!;:=' Rp6p !M0|o/^?}lC<;o[;;U3WEt\A*=Z޽ M띧?_YXz}*@ w11_e]p},ŮF ײc#2l2MuVHH/8 ذD'gx6i"p j{/ޟ [d(r\1%.*Us"<`V (3:K @ev=gX&8K{5asRթO}|A ΢WiqԆb63 #X 4:28O[=Sf"\֮=moE\:S77 |~0pG:yXXe7Ot9`\qw{ZfzYNϺ﹫v V &bf|`ׅi3[Pp~7-Fa4U,aDliU AȕS0R.[{O&,L1|]Ayޓ ]oPs_À~M 7RZL+;uyaE:cwHQ`RPpLt(?=^VK ˖}WU l~C,)'K\֫!Mמ^u  РӉ=ˤDom#!h Qy,X2LF箌I7EŎ7Һ4ci}K<^EbtŨ7b9ʧwTi=5x_">R#;ie}J6EԔb#qkCj|[4vh0Ȫr#_Z\(Efm6O]}6倖Kq{PϸO[y\.{hvfcpysc$7ݯ:?FFSV ̯#^i !M #J!!_xPIs/hbʼg~G>6Q}uZ.%Y|*GZ0L? ^_AP 䯗Y$OQ,fnwyLŹ9l]ۺ5\?G3,4_7ϯ"Z8%l-;Y;a1Xr²"z 5P'WRؤ?"Rn"Q eo*)xEI sl 1ckFSL/Zth 1w}k ;ikR" dj -ۊ/]3LNJj^Ը<]R sDự˭%&TFcFk)RĚ-8;~KhX $9&HFX_N.X#pdj\z}ZHH#phZ=1L6qK^ Fydj:& $?Y];:^këZ~3 ց*[Pq]᳨`pW#Nxyœ-xvMC;< -CdX,SJn FOFόn|O!vp8E䬬d`yL?=Ӄ[zWPȆ~!r%[.x̥~l|7 3̶Ye:}%*cXc}t*bY  ;Z$ LRiRowi6bAw+½ &m·Ma`=eH(n_t+mV;4kˡZ٧k(h#j!Rt{^QI󨥞ҋPunDϼNPzGDg^"Ho7yoI7PKa8F#<; &&dT9uhOIg< _!>TcT( DB R_5K(T:Ň~#蕲qB!^pSc1}ݦ$27;6DBj2{vlsc5<hoXZlsqwׂkeryj.v-k> c;č]1,4&OؑAdW0|mJz8#-*]ɭҐIB_nw>LM?/r{^_;kB܂1f ߨv'֜e!BkIEv&#hK6 Pxf&B|4bLj !9]o<] ㄍ", S:v !KŮ}@bQ=R5"? 1)쭺]䅎>JFCWAכf~iif-h򁑚g"1j"ޡZۯRPӝ~K?aX1s[ShcMzTڪ" Yoa;@ӣS#iJr*Mm$2cS>v(@I l5pΤKЪPݽm/^o1/t5xt9n`e_K^)utҮCuF ^W>;)~^8#:}l]ײ^x-f>-3OxHV#5G3|+<OOzsS:fO]Zڴ(2h-iE;\6}m\m_PM*k۰q:x'ΨfԨ6⛁f9/]4n| .T&5F [C!hZJnDx/lD`o4A#2WZCJDK*?Cqmɣ 6m> KhLіky GP*>l@Nh֨P{`OP:[y@7iC8T?~2+q\实tAﱇC!čjG'63IP#"1pu;?x)L~N`yІS{[^:Х)r@&=4N@8}Hڙ81nbaopI [5/Z]f5 "O+ uBIxo'r I H+bI@]A`c;b0ރIgyjOҾk5f=Qk_TX@ͩf<7kܴMO>j~,)*ޚڰ&plWaC~Mw J>MC`2X!bTxEᓖj LZ0m2<0.:+ ްKf J0sx8=ZZ!bcIBM\D+>h- cٞB@\79< 0dL$`< hx !}ä*1BSQq h("&y Akq p,BQVs3˂%J B-Ӂ#țc!S7OH@N"99E'&T*C^⩹RVp n(ipIqyCɣ,Q!U7-YO1#v7DS؍.MBv[ gIH&@,f? r&dk3`I)anhR;'i9KeAc1J5w1y;،ݎԣrx}~@9(|=ְthTft*T~EK5 7)+*z[ R |IUo{?ӕVaJhؚLh)A6Vf [qhۭa"(ͩa 鋳q"+8{">52mjDBI2-gdhS?}jY<Gͤ/'Ztܙ׼A hhSľ|E˰tPS&yɜ!7" ~m]~QWR,^*N6SzvF=خmތ-g>;^ӁP e\qNzn?O=5h FcPoIեT n(t⼮Qͳge~[bwl)-zĻAPYӦ }GmQ¾L(8uQS1V;@X-u: r[ز8Д^!MT4Ouԕ{^DGk. 0;(?GnknϜ:t!FGηq,G}Ff{g~Ug߭6o`{.\?"L] O;¬6f:OM#8._| H]1'X vGT)IP[td03B1H57s<05prfW5c2KAeLZfio^,-"i`9*SK~@hιCcña&pWGLD&׋K^gI|Z!?idR@@I?*-4u{NiI?ebR{s4:nFX jO@@ѣԌ^C޾7gY"@gV_|3`E<)Շ^_jUʰ[a9S;e:gqlPFi+!q%T՛7.^O'e n3gnãȏrTX~LD,'i*dkqq:6nM?ݩu7G?UޫG{zS "/3g1OmVo33l^u'K]_1e ܖl5$&FPil'_be40`П%huM($d{ԏIZ㤻3g?tvi~ZU^Lm"qi5mm,ܝVS}Gs+kݒ>:A;n&s=^!t#OfrdCՕ:4QM6huzO4MrT8R|$Y ;gG!Q ]2Ħ sl]\wF.R=}ȶIx%>PD֑2="#! D,bLR"MervL^LZrlGoO+g|Re#6OfJQSYe}HGJF\M?3T`QD-Cc lf{:4,Ej0U"v&Ԟ0w'i^a!%<ʦ(ev I&(\}zF'D3TD^Rl4ӘN).γ1☠y*,J/hR{U^`*pl'q2=m5xR I,~-[ϰKj4.jozJ_t Ў$z1y&}u⠻]\c n헇`_TDhy8șqŻ Įr둲kȰt, ~v½"h74^x2V)FU%?"Miݐm`}{X"\yO]U/)vj1 &}NOʬQO7 ",_I>K?°+C CiE%qvM*d:6 =T.', ݄;m7Շp{VBPW<%cK1 m #N q-XtOdA6 ,<3>lσ^R\{P}3Y4O~+n-.w]/TK% \JU߮ eEQr !k-F)K7Az@3\f͍Lcfm|i֔R^œ5i4@Է^⒂aҧuquU03\],b AR|ns%6g;[rA+/}t=㽦͈m{yJѩ}7#FT70I 9&^[}d=BqFY䅡#%1'$ x1h@۽TbXś%]XH& }ؐ鹴y|XHj D1yP ^95|f(A h`j C>^@oqHrGqT*{5ѺgiM|QOD gZh)7'Q׶dRϐ^sc cK͟NhB+]ֳgp ? gj;;D,~#xM3$ H 2,H,nЬ-S8=Ͽj \3y្j+8#j~YI?|x FY.,bU[tP!3jT=aP%) t׼;]WQ&@ 5i5ȇjP.F3UJVS嘧nYo/D x0#VTNP741EFZ #W܀ܫk76Kn$ېZMm"VҜ*hc2I&w%;x9b%O;:kn9wBVd&9DM,]LxYid?gߊffK _TawSQ~eI>.~=Kƕ8WO iHQQ(#$(`zFlZR{d$5@'Y4ׇ`XW>ۥt=j,0e-F +܇M/WT-R5wɨ~h ZU[*Z@QY)#H~9=f]y%&Ž7Nh7NW$>$if~!`pA2co`3,;>-^h YUVM8X 2kvA B1y %a}.XvEB1rK lXg/$].BoEHa)1eXhk_ AQ é7ڦ>,1Vulpz}kpCOdT; 2{3/*I<^ZѦzMG+џ-UXfq0K{iq߹ȸc>gr؋uL|ZhU,N x C[t!^An9}kGvw4/lDpU+MYY7XY_=fYP֫=EB >4> I4}`kQHrO'o5o&[2:v#pP|=H )IaqkF5YY:!!~kHʞ"@_FN)^ƍ?2*wV~_O&!XE谳Ş}%{;mӪҜ N 2a?mh>Faf_`#Y!-Ii#ު%RH͉[n1뱒ʇ}P g2' AےlV_R%#WTpI,ӵ:g).n;(b0Y\CxT^m!1](nvO::,}EŴ C"/z34B)Wmn&+W #zULTb5PjI8-#dCb% *4)b%#vڈ48-z43>!XNΐG %QV}5f(Kqh`͒ >;1'Z.ړQFW\G0_c%{A/E9D͕hnG <}˓j†*AR\m] 4T-Ug\1!=M< ~zCΝs4If wh~AG]) ) *f'EBr'Bæh[Ҋ!g)(=~0?qbsߴAhu36f64~@{rJeyfY{\cp&QSch;Ϙe|:QhH8L-$IW_ZF/}3R sNYRg# ?܏' B*=G ?IQ0f ?DYS͙Zz}NM%fr_秸6Fbq@J^WT5WfwhZ~ȃP+{UFբfʼҴpw.BBfiB/?_lZ~9s)+1Ջgnԓ62Yv„yH)[ oԉ&Ik<,A).e_Q\ɗ,",k7k]_nt >%It + YndIyM2O& ~9,Cgƴ6`W0[j !wٿN07a`:iB<6A1'#VT6U a#/;3z|RRoQP*T[vӕtN?Ai#s0Ԩv=&6(4q Γxa uQ;v^ʬGP!o-WY 5"e՚{V68v"tWJ蘨apïo[}EzQC9e*y@{2CPgRT)V:a˽;Lۓ TW GfxZCf)1FDWf)dAm76zO:+`:q\FoNd\72ͭ?X% mv!ġAC%e`k:?uGt$9TU@nȁZ Ax9j~BT?~q: W$2G`bŅvO`P!ϲuz-yُꈨPה8 endstream endobj 97 0 obj << /Length1 721 /Length2 6909 /Length3 0 /Length 7498 /Filter /FlateDecode >> stream xmwuTk5R5t 30 2tJ ]t4 HJIy}}׻ַ~>g?g=k8X5'TD@DPX`a/",##PCAAh,  " !!=Q0W4ۉo`A`0 G>9>}G( ]g P3Zih5 P>`8 s"<g$ '8!_x EsF!=*u5!S5iiGeN("U? sBPH/ߴH?0Ax@}pACQ}$B Ŀ, C s@0o X oϽC!0s$?G􍍁f|-euCL  ? >lZ῾#e"Dbqq hBA 3˿ߋAfNrn!E|㣎f|"s#G6^WS|_0I(Jy85nᲘ%jڨ6Ϝ(ݭ*Us,k'_y5?u̴M{G>tFrAZX5TIfuYx*h6h'gg~ʧd(MK~ 2@4KZ*,bfIvjA:7"I쮿eW3}ݔ0`o~ϔiRm.*2ua-ɗ!FYicD'jz>+dDBKx|'V6_x_w'ȽiB&Jw'M* {b#"߼p7)T)M¹hkXw6=Y,* ׷]ٌq or>+'~\"&3P"><_{3z `<,G/oM >+f4h,h3Ʈ V=6dEMo1dnhe>/ȍrf SN`f]ȃ)%IFڪڕEi,n]t!T>sffVx]ͭ](pxu8^\Efa }0iOO nMl: 9]%iL #ǥdOxԓ4Vu|K* eOtn>ʿ1ډ6fWqiڄ︯OBٛn0?tZUc7$GdXP*=kDɠyBe/r-r8wlt9*[ /{#NI53~rݡ0&xͮ >،}*6qDg%ҿG@j3KC 'eԩ 6짹3 '0wτ-}0|KH)'QAɸ nGCK=vrȐ޷?6j `#i9Iݝ“0u ^iV)g=qAp-`j*ǔAoS5ѝۆ>F:!jkTOTwq7OS7KD]a =Hh"xS#%o~+#+R:иa T<.l3_|V{{4.9jV Q^C)}RWG͖ P$a6]mM_42TUjj͆m~KNT]16RR q->hlsFcs~ ~OAɳ<z*}oLsGKa[@h;U1o9Uxqeb~gf/^$@:W=CZ J";K 8 EAgzE.M/1!ݑmН=<2+gեrPɛQh4c|& Ͼ'|aׇeޤ/ZEԌYk>!wn?Zʡ9l e/2@g;?z2$铵ЦO4~C.iJؔrIkRDP4*PWw+TO8!CՓ$S&O,o]ULUh2v͐N9Ռs&вĭMhc&WwڌRlu'~p晻 1g2p˒>(+4v$ pie`"!\3okWɥUT|NS?j K&?Rf ߠIeS[b[}{\w_SG'!Q31~XWΪwqjV cOtg[}i*`Aw9nd!.b :pr3oX!S1Qyez1H1;ۗ3>NN+ᭆld 6Ufi YB3VMZⷀga%ڵwL^O88 xP̷w-7;kKj},cv&ub:qD{qӦ95"  \YH${#)s`AXKn6Kݝ;c804rdYA74MAѡQ]$AJ'ݸ!􄕝M[KXeI͉tE"Tr}~is :u<1x=CmVyn25:A7|%55@x=dǍH>`ϱvBA}csoTur>KmY0s0G\ K-o9evVb*>䢻pKrZAf,LF ݄IՖ4;S)!Q޼񣮍@X=ah>c`"](umX^A"1Y2%L@ z߯wMK'ԎP&+b QLK /pb1Kk^1aaO145gZS瞍Q:Lc7slT6 Ҁ,1k3;KY6PvŷJY,L] D^\}K*̍bWQp [GCYgm9U2sd% FO;P/w wo"6{^Bgʨ$e%XP<֦mx4;5 ɱJռHg?:S0k.O=Œ7&I} +1{]o}yHwwK: wlyzMtg؏jx6[݆)Qƾ5-JzVansf8Gfϥaos/Q=e}ւc1T1˨ ߏ1`hWg@FLuyn %T]|,J9? -fZY0$atӫMG7<MNX2 +t0jАUU@5%)r`%6.tY29=E/wlaE ӤY&(Zuj>Y"l_я 1b}Tϓ)Ks,И nUoDnJTl~H 7z2UaӬm'a^kn~Yz?#4n.E/zMGR^Od,JJZΊ؉C-ا H5wk?\sutVrlm ;gפj 8߅}@9 (]jG2Ucًq|*1YݾfdE5läkFZ{1mDɝWjs3Ud4f5rv_JJi ď/<7ewt$|x >n{Ł#٥ 2?Z_iy\q^(P'6Х{+a8sY|:0Lx@ p}l^4)dh>`6A<3]oVŊ}%+ӟ=y[0 ." 3M-IY)^߫G{|+q"IbYLpp @Z-^: %4d L߉mcדm*}r<KwZ*_{f=uF\e&G'WfE ;R(nkK=$J0}]BuU~ ἅuֵiU;r .COvIM=*GE+ xOW-n"~_{z ?7 :Oԍ>~ZMMف9H~+yo* ƒ0n;)o.B춬u^# 8P˶8':wDO*3~6U'gs)>hN.{4|~Nc0FVhՎh&NB MٻȚl.cg+U1C,44#'`Lk)u*T/MFeIu:i8HQV$ 'ށOI@eBEwK2G?Z}N!V5W{ٟrf(Cm%ɧ Q v o%5akeO(kR![{Ma`s4s~L鲲>YQmyq3F6˒>v?eoJ]kfdU5  `7&b]rBYOm_Kv_Y}~7fŖ'‘Y S69v2~hu"^nRSm]7ٔ|޵ *Օ?ڱyg&mb|u_&> ӣfDt6rW\{t9Iܐt̺u_Uo nbVsnG թ9 C0]_ !<=ۼ a:q1aa7 T{Ү(kF3 2J,B*Kn> 3䑆Z-ZSGFJS endstream endobj 105 0 obj << /Author()/Title()/Subject()/Creator(LaTeX with hyperref package)/Producer(pdfTeX-1.40.18)/Keywords() /CreationDate (D:20190514213502+02'00') /ModDate (D:20190514213502+02'00') /Trapped /False /PTEX.Fullbanner (This is pdfTeX, Version 3.14159265-2.6-1.40.18 (TeX Live 2017/Debian) kpathsea version 6.2.3) >> endobj 2 0 obj << /Type /ObjStm /N 87 /First 688 /Length 3434 /Filter /FlateDecode >> stream xZ[s8~ׯ@V;c[ٲv:8IO)?(ck"j;%屒.[  !X S98wLL˄bB㢙 Ǥ3)ˤq)Ihmäeh !0 Bi Hm@orˆMgA&Ubˆщwa!ú<Ϩ(NXa%wtd{ ܞ"Mm5Qe?vc:?E ⟞0lF*@mH:T=~X1c]bʻ2H!FL8/[Ǐ#~/{t4|4i({6Y1^/v\Mgޫ1?O=bӔflv`qD"w?rH/(m?Bc5WeQoV^FmZ;F><0IZҾZ]k[ᶴaQ> i-yx.m@~bĊoKC&mFZ&wC)Ye#P6+fd>`B #9=|^VMYβp^~SziͫêbY]Cή gb>/ajSea+ޙwRCfs_^QUJel;?@Z2 v a7C0/};,Zlh|KW) g 68 :w-ezODA~K[ $ 36JZhޙa)R_(k؁7 ШgѾLԌ8}گd8*#?2_qa=s Z%Sjʂ'xg\sh. $_0V> n=p*A=gvzA<[uuph=k?|!6~*}-#5> =SO<{话m˺mN'Ik\I8T,Fu!;m[ŹOLW7yV~_ȓb&V`&QU } 8OafSR0HRut09TN;ҁo>^%,'d" zݰn[kjJf%j 11W `.J%I{^ǑBܢu>tHMHn^r=b$ZhcH eg/C,qF =gȒqĹ(cہOT}VOv%VcKMtF<%!@Rdk#-tL\TdAe{C:G z ʎ4þV{ -|'U;#JIK ДkG616ԊBۏyL[P*\|D\vv\xZԣj2o*m1^ ohg񻳟`:Nq#z$;L/pD#ڎD`W;SNH=| jZ`Mq3rߵ2\+ڟ<®3$N&\mُ/~yVKal)L9+|ys[d ӓ7Ē$}`;R ѓnWR7ʾ ˇ#X GfZ|jfSlG͐y_&_ ~ůob'|ʧE]>Ǣ'W3^&9c/!դ׼| o E_1*7} g3bH^E nTwuWG? gEuԟaQWQml<''<Eշ?d c]DƢe/շ͗I1ʫ'O=[2ahNQN)mG}~+r;}$?zi-;!+s;L3BpH k+xz:ynW9x>n Osgm֎Jѳ -9EOU{UvIT2RSߑ)ڒ|3:Qܮpa{۟ir~g (\6əl(߶Dw3-<{%7ߑ ).E!AxX+):?'L!Va{#h?&溦#`w>k>mo]ڦCOz{ɼA]nRW+kf z8qZwj vKz$\lr8w&n'b[>BOv&'U7o=횺ܟf syv'7 -SvW}ͷS-}+2 A-[~M z/&zu=h"/^-gEM͒r(3tf9=xV_j8SL}M_'b߁F K$v7!q#wzŃV0֣V&=ìttRν<{u@g`/'7frDyN[?Ƅ7 쉰^trbo:L8=10:JOXDWS-X2jNMf*Nq:F:ʞt endstream endobj 106 0 obj << /Type /XRef /Index [0 107] /Size 107 /W [1 3 1] /Root 104 0 R /Info 105 0 R /ID [<28F477E4EE760C495D2D4AE8A5FAE93D> <28F477E4EE760C495D2D4AE8A5FAE93D>] /Length 264 /Filter /FlateDecode >> stream x%.QZCyUy vA"k{l>ޜffY`ˇQ 8ApPMpEP m%؃0BCD YwA*T:B(l,&lA!) ?X#C,rg ] vC d`F``&dɄ2)K{M/R eO1kF zJל.wE؅c8S8|oK" endstream endobj startxref 120502 %%EOF gower/inst/doc/intro.Rnw0000644000176200001440000001144113452644704014754 0ustar liggesusers%\VignetteIndexEntry{Introduction to the gower package} \documentclass[11pt]{article} \usepackage{enumitem} \setlist{nosep} \usepackage{hyperref} \hypersetup{ pdfborder={0 0 0} , colorlinks=true , urlcolor=red , linkcolor=blue } \renewcommand{\familydefault}{\sfdefault} \setlength{\parindent}{0pt} \setlength{\parskip}{2ex} \title{Introduction to the gower package} \author{Mark van der Loo} \newcommand{\code}[1]{\texttt{#1}} \newcommand{\pkg}[1]{\textbf{#1}} \begin{document} \maketitle{} \tableofcontents{} <>= options(prompt=" ") @ \newpage \section{Gower's distance measure} Gower's distance can be used to measure how different two records are. The records may contain combinations of logical, numerical, categorical or text data. The distance is always a number between 0 (identical) and 1 (maximally dissimilar). An easy to read specification of the measure is given in the original paper. Gower (1971) \href{http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.412.4155&rep=rep1&type=pdf}{A general coefficient of similarity and some of its properties}. \emph{Biometrics} **27** 857--874. In short, Gower's distance (or similarity) first computes distances between pairs of variables over two data sets and then combines those distances to a single value per record-pair. This package modifies Gower's original similarity measure in the following ways. \begin{itemize} \item{In stead of the original similarity $S$, the package returns the distance $1-S$.} \item{The original paper does not mention the concept of \code{NA}. Missing variables are skipped when computing the distance.} \item{The original paper does not mention character data. These are treated as categorical data.} \end{itemize} \section{Computing Gower's distance} The function \code{gower\_dist} computes pairwise-distances between records. <<>>= library(gower) dat1 <- iris[1:10,] dat2 <- iris[6:15,] gower_dist(dat1, dat2) @ If one data frame has less records than the other, the shortest one is recycled over (just like when you're adding two vectors of unequal length) <<>>= gower_dist(iris[1,], dat1) @ It is possible to control how columns from the two data sets are paired for comparison using the \code{pair\_x} and \code{pair\_y} arguments. This comes in handy when similar colums have different names accross datasets. By default, columns with matching names are paired. The behaviour is somewhat similar to that of base R's \code{merge} in that respect. <<>>= dat1 <- dat2 <- iris[1:10,] names(dat2) <- tolower(names(dat2)) gower_dist(dat1, dat2) # tell gower_dist to match columns 1..5 in dat1 with column 1..5 in dat2 gower_dist(dat1, dat2, pair_y=1:5) @ It is also possible to explicitly ignore case when matching columns by name. <<>>= gower_dist(dat1, dat2, ignore_case=TRUE) @ \section{Computing the top-n best matches} The function \code{gower\_topn} returns a list with two arrays. <<>>= dat1 <- iris[1:10,] L <- gower_topn(x=dat1, y=iris, n=3) L @ The first array is called \code{index}. Each column corresponds to one row of \code{x}. The entries of each column index the top $n$ best matches of that row in \code{x} with rows in \code{y}. In this example, the best match of the first row of \code{dat1} is record number \Sexpr{L$index[1,1]} from \code{iris} (this should be obvious, since they are the same record). The second best match is record number \Sexpr{L$index[2,1]} from \code{iris}. The second array is called \code{distance} and it contains the corresponding distances. \section{Using weights} Gower's distance is computed as an average over differences between variables. By setting \code{weights} you can compute the distance as a weighted average. <<>>= gower_dist(women[1,], women) gower_dist(women[1,], women, weights=c(2,3)) @ \section{Parallelization, memory usage} The underlying algorithm is implemented in C and parallelized using \href{http://www.openmp.org}{OpenMP}. OpenMP is available on most systems that can run R. Please see \href{https://cran.r-project.org/doc/manuals/r-release/R-exts.html#OpenMP-support}{this section} of the writing R extensions manual for up-to-details details on which systems are supported. At the time of writing (spring 2019), OSX is the only system not supporting OpenMP out of the box. You can still make it work by installing the gcc toolchain and compiling the package (and R). If OpenMP is not supported, the package will still work but the core algorithms will not be parallelized. This implementation makes no copies of the data in memory. When computing \code{gower\_dist}, two double precision arrays of size \code{max(nrow(x),nrow(y))} are kept in memory to store intermediate results. When computing the top-n matches, for $k$ cores, $k+2$ double precision arrays of length \code{nrow(y)} are created to store intermediate results at C level. \end{document} gower/tests/0000755000176200001440000000000013465343632012550 5ustar liggesusersgower/tests/tinytest.R0000644000176200001440000000010513452644704014552 0ustar liggesuserslibrary(gower) if ( require(tinytest) ){ test_package("gower") } gower/src/0000755000176200001440000000000013466614147012200 5ustar liggesusersgower/src/Makevars0000644000176200001440000000011013452644704013661 0ustar liggesusers PKG_CFLAGS = $(SHLIB_OPENMP_CFLAGS) PKG_LIBS = $(SHLIB_OPENMP_CFLAGS) gower/src/R_register_native.c0000644000176200001440000000171513452644704016020 0ustar liggesusers#include #include #include // for NULL #include /* FIXME: Check these declarations against the C/Fortran source code. */ /* .Call calls */ extern SEXP R_get_max_threads(); extern SEXP R_get_thread_limit(); extern SEXP R_get_xy_range(SEXP, SEXP, SEXP); extern SEXP R_gower(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP R_gower_topn(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); static const R_CallMethodDef CallEntries[] = { {"R_get_max_threads", (DL_FUNC) &R_get_max_threads, 0}, {"R_get_thread_limit", (DL_FUNC) &R_get_thread_limit, 0}, {"R_get_xy_range", (DL_FUNC) &R_get_xy_range, 3}, {"R_gower", (DL_FUNC) &R_gower, 8}, {"R_gower_topn", (DL_FUNC) &R_gower_topn, 9}, {NULL, NULL, 0} }; void R_init_gower(DllInfo *dll) { R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); R_useDynamicSymbols(dll, FALSE); } gower/src/gower.c0000644000176200001440000004524513452644704013476 0ustar liggesusers/* gower - a C/R implementation of Gower's similarity (or distance) measure. * Copyright (C) 2016 Mark van der Loo * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * You can contact the author at: mark _dot_ vanderloo _at_ gmail _dot_ com * */ #ifdef _OPENMP #include #endif /* R-windows-oldrel (3.2.x) uses gcc 4.6.3 which we need to detect */ #ifdef __GNUC__ #if __GNUC__ <= 4 && __GNUC_MINOR__ <= 6 #else #define HAS_REDUCTION #endif #endif #include #include #include #define MAX(X,Y) ((X) > (Y) ? (X) : (Y)) #define MIN(X,Y) ((X) < (Y) ? (X) : (Y)) #define RECYCLE(N, K) ((N) + 1L < (K) ? (N) + 1L : 0L ) // determine when something is numerically zero. static double EPS = 1e-8; // set max nr of threads to use static int NTHREAD = 1L; // recycling in parallel region. static inline int recycle(int i, int nthreads, int ni){ i += nthreads; if ( i >= ni ) i = (nthreads < ni) ? (i - ni) : (i % ni); return i; } SEXP R_get_max_threads(){ SEXP out = allocVector(INTSXP, 1L); PROTECT(out); INTEGER(out)[0] = 1L; #ifdef _OPENMP INTEGER(out)[0] = omp_get_max_threads(); #endif UNPROTECT(1); return out; } SEXP R_get_num_procs(){ SEXP out = allocVector(INTSXP, 1L); PROTECT(out); INTEGER(out)[0] = 1L; #ifdef _OPENMP INTEGER(out)[0] = omp_get_num_procs(); #endif UNPROTECT(1); return out; } SEXP R_get_thread_limit(){ SEXP out = allocVector(INTSXP, 1L); PROTECT(out); INTEGER(out)[0] = 1L; #ifdef _OPENMP INTEGER(out)[0] = omp_get_thread_limit(); #endif UNPROTECT(1); return out; } // presence or absence of a character. x and y are 0 (FALSE) or 1 (TRUE) static inline void gower_logi(int *x, int nx, int *y, int ny , double *num, double *den, double weight) { #pragma omp parallel num_threads(NTHREAD) { int nt = MAX(nx,ny); double dijk, sijk; int i = 0, j = 0; double *inum = num, *iden=den; int ID = 0, num_threads=1; #ifdef _OPENMP ID = omp_get_thread_num(); num_threads = omp_get_num_threads(); i = recycle(ID-num_threads, num_threads, nx); j = recycle(ID-num_threads, num_threads, ny); inum += ID; iden += ID; #endif for ( int k = ID; k < nt; k += num_threads, inum += num_threads, iden += num_threads){ dijk = (double) ((x[i] | y[j]) & !((x[i] == NA_INTEGER) | (y[j] == NA_INTEGER))); sijk = (dijk == 1.0) ? (double) (x[i] * y[j]) : 0.0; *inum += weight * dijk * sijk; *iden += weight * dijk; i = recycle(i, num_threads, nx); j = recycle(j, num_threads, ny); } } // end parallel region. } // equality of categorical variables, encoded as x, y in {1,2,...,N}. static inline void gower_cat(int *x, int nx, int *y, int ny , double *num, double *den, double weight) { #pragma omp parallel num_threads(NTHREAD) { int nt = MAX(nx,ny); double dijk, sijk; int i = 0, j = 0; double *inum = num, *iden=den; int ID = 0, num_threads=1; #ifdef _OPENMP ID = omp_get_thread_num(); num_threads = omp_get_num_threads(); i = recycle(ID-num_threads, num_threads, nx); j = recycle(ID-num_threads, num_threads, ny); inum += ID; iden += ID; #endif for ( int k = ID; k < nt; k += num_threads, inum += num_threads, iden += num_threads){ dijk = (double) !(x[i] == NA_INTEGER || y[j] == NA_INTEGER); sijk = (dijk==1.0) ? (double) (x[i] == y[j]) : 0.0; *inum += weight * dijk * sijk; *iden += weight * dijk; i = recycle(i, num_threads, nx); j = recycle(j, num_threads, ny); } } // end parallel region. } // strings. Treated as categories. static inline void gower_str(SEXP x, int nx, SEXP y, int ny, double *num, double *den, double weight){ #pragma omp parallel num_threads(NTHREAD) { int nt = MAX(nx, ny); double dijk, sijk; int i=0, j=0; double *inum = num, *iden=den; SEXP xi, yj; int ID = 0, num_threads=1; #ifdef _OPENMP ID = omp_get_thread_num(); num_threads = omp_get_num_threads(); i = recycle(ID-num_threads, num_threads, nx); j = recycle(ID-num_threads, num_threads, ny); inum += ID; iden += ID; #endif for ( int k = ID; k < nt; k += num_threads, inum += num_threads, iden += num_threads){ xi = STRING_ELT(x,i); yj = STRING_ELT(y,j); dijk = (double) !(xi == NA_STRING || yj == NA_STRING); sijk = (dijk==1.0) ? (double) (CHAR(xi) == CHAR(yj)) : 0.0; *inum += weight * dijk * sijk; *iden += weight * dijk; i = recycle(i, num_threads, nx); j = recycle(j, num_threads, ny); } } // end of parallel region } // comparison of numerical variables, by absolute difference divided by range. static inline void gower_num(double *x, int nx, double *y, int ny,double R , double *num, double *den, double weight) { if ( !isfinite(R) || R < EPS ){ warning("skipping variable with zero or non-finite range."); return; } #pragma omp parallel num_threads(NTHREAD) { int nt = MAX(nx,ny); double dijk, sijk; int i = 0, j = 0; double *inum = num, *iden=den; int ID = 0, num_threads=1; #ifdef _OPENMP ID = omp_get_thread_num(); num_threads = omp_get_num_threads(); i = recycle(ID-num_threads, num_threads, nx); j = recycle(ID-num_threads, num_threads, ny); inum += ID; iden += ID; #endif for ( int k = ID; k < nt; k += num_threads, inum += num_threads, iden += num_threads){ dijk = (double) (isfinite(x[i]) & isfinite(y[j])); sijk = (dijk==1.0) ? (1.0-fabs(x[i]-y[j])/R) : 0.0; (*inum) += weight * dijk * sijk; (*iden) += weight * dijk; i = recycle(i, num_threads, nx); j = recycle(j, num_threads, ny); } } // end of parallel region } static inline void gower_dbl_int(double *x, int nx, int *y, int ny,double R , double *num, double *den, double weight) { if ( !isfinite(R) || R < EPS ){ warning("skipping variable with zero or non-finite range\n"); return; } #pragma omp parallel num_threads(NTHREAD) { int nt = MAX(nx, ny); double dijk, sijk; int i=0, j=0; double *inum = num, *iden=den; int ID = 0, num_threads=1; #ifdef _OPENMP ID = omp_get_thread_num(); num_threads = omp_get_num_threads(); i = recycle(ID-num_threads, num_threads, nx); j = recycle(ID-num_threads, num_threads, ny); inum += ID; iden += ID; #endif for ( int k = ID; k < nt; k += num_threads, inum += num_threads, iden += num_threads){ dijk = (double) (isfinite(x[i]) & (y[j] != NA_INTEGER)); sijk = (dijk==1.0) ? (1.0-fabs(x[i] - ((double) y[j]) )/R) : 0.0; *inum += weight * dijk * sijk; *iden += weight * dijk; i = recycle(i, num_threads, nx); j = recycle(j, num_threads, ny); } } // end of parallel region } static inline void gower_int(int *x, int nx, int *y, int ny, double R , double *num, double *den, double weight) { if ( !isfinite(R) || R == 0 ){ warning("skipping variable with zero or non-finite range\n"); return; } #pragma omp parallel num_threads(NTHREAD) { int nt = MAX(nx, ny); double dijk, sijk; int i=0, j=0; double *inum = num, *iden=den; int ID = 0, num_threads=1; #ifdef _OPENMP ID = omp_get_thread_num(); num_threads = omp_get_num_threads(); i = recycle(ID-num_threads, num_threads, nx); j = recycle(ID-num_threads, num_threads, ny); inum += ID; iden += ID; #endif for ( int k = ID; k < nt; k += num_threads, inum += num_threads, iden += num_threads){ dijk = (double) ( (x[i] !=NA_INTEGER) & (y[j] != NA_INTEGER)); sijk = (dijk==1.0) ? (1.0-fabs( ((double)x[i]) - ((double)y[j]) )/R) : 0.0; *inum += weight * dijk * sijk; *iden += weight * dijk; i = recycle(i, num_threads, nx); j = recycle(j, num_threads, ny); } } // end of parallel region } // range computations static void get_dbl_range(double *x, int nx, double *min, double *max){ double *ix = x; double imin=*ix, imax=*ix; for ( int i=0; i imax){ imax = x[i]; } else if ( x[i] < imin ){ imin = x[i]; } } } }// end parallel region *min = imin; *max = imax; } static void get_int_range(int *x, int nx, double *min, double *max){ int *ix = x; int imin = x[0] , imax = x[0]; for ( int i=0; i imax){ imax = x[i]; } else if ( x[i] < imin ){ imin = x[i]; } } } *min = (double) imin; *max = (double) imax; } static void get_range(SEXP x, double *min, double *max){ switch( TYPEOF(x) ){ case INTSXP : { get_int_range(INTEGER(x), length(x), min, max); break; } case REALSXP : { get_dbl_range(REAL(x), length(x), min, max); break; } } } static double get_xy_range(SEXP x, SEXP y){ double x_min = R_NegInf , x_max = R_PosInf , y_min = R_NegInf , y_max = R_PosInf , min, max; get_range(x, &x_min, &x_max); get_range(y, &y_min, &y_max); if ( isfinite(x_min) & isfinite(y_min) ){ min = MIN(x_min, y_min); } else if ( isfinite(x_min) & !(isfinite(y_min)) ){ min = x_min; } else if ( (!isfinite(x_min)) & isfinite(y_min) ) { min = y_min; } else { min = NA_REAL; } if ( isfinite(x_max) & isfinite(y_min) ){ max = MAX(x_max, y_max); } else if ( isfinite(x_max) & !isfinite(y_max) ){ max = x_max; } else if ( (!isfinite(x_max)) & isfinite(y_max) ){ max = y_max; } else { max = NA_REAL; } return max - min; } SEXP R_get_xy_range(SEXP x_, SEXP y_, SEXP nthread_){ NTHREAD = INTEGER(nthread_)[0]; SEXP out = allocVector(REALSXP,1L); PROTECT(out); REAL(out)[0] = get_xy_range(x_, y_); UNPROTECT(1); return out; } /* static void print_vec(double *x, int n){ for ( int i=0; ii; j-- ){ topn[j] = topn[j-1]; index[j] = index[j-1]; } topn[i] = x; index[i] = ind; break; // out of main loop } } } } /* For testing purposes SEXP R_pushdown(SEXP entry_, SEXP index_, SEXP values_, SEXP indices_){ double entry = REAL(entry_)[0]; int index = INTEGER(index_)[0]; double *values = REAL(values_); int *indices = INTEGER(indices_); int n = length(values_); push(entry, index, values, indices, n); return R_NilValue; } */ static inline void copyrec(SEXP into, SEXP from, int i){ int ncol = length(into); SEXP col_from, col_into; for ( int j = 0; j < ncol; j++){ col_from = VECTOR_ELT(from,j); col_into = VECTOR_ELT(into,j); switch(TYPEOF(col_from)){ case LGLSXP : { INTEGER(col_into)[0] = INTEGER(col_from)[i]; break;} case INTSXP : { INTEGER(col_into)[0] = INTEGER(col_from)[i]; break;} case REALSXP : { REAL(col_into)[0] = REAL(col_from)[i]; break;} case STRSXP : { SET_STRING_ELT(col_from, 0, STRING_ELT(col_from,i)); break;} } } } /* for testing purposes only void prvec(SEXP x){ for (int i=0; inrow(y) and sets n=nrow(y) - bugfix: comparing factors with characters would cause a crash (thanks to Max Kuhn) version 0.1.2 - fixed valgrind warning - registered native routines, as now recommended by CRAN version 0.1.1 - gower_dist now issues warning when nr of rows on input do not divide (recycling) - Code now depends on gcc version for compatability with Windows + R<=3.2.x - Bugfix: bad range calculation caused faulty distance computation version 0.1.0 - First release gower/R/0000755000176200001440000000000013452644704011607 5ustar liggesusersgower/R/gower-pkg.R0000644000176200001440000000104513452644704013634 0ustar liggesusers#' Gower's distance/similarity measure. #' #' A C-based implementation of Gower's distance. #' #' @name gower-package #' @docType package #' @useDynLib gower, .registration=TRUE #' {} .onLoad <- function(libname, pkgname){ max_threads <- 1L max_threads <- .Call("R_get_max_threads") thread_limit <- .Call("R_get_thread_limit") max_threads <- min(max_threads, thread_limit) # leave one core for the user to control the machine. if (max_threads > 2) max_threads <- max_threads - 1L options(gd_num_thread = as.integer(max_threads)) } gower/R/gower.R0000644000176200001440000001562413452644704013065 0ustar liggesusers #' Gower's distance #' #' Compute Gower's distance, pairwise between records in two data sets \code{x} #' and \code{y}. Records from the smallest data set are recycled over. #' #' @section Details: #' There are three ways to specify which columns of \code{x} should be compared #' with what columns of \code{y}. The first option is do give no specification. #' In that case columns with matching names will be used. The second option #' is to use only the \code{pairs_y} argument, specifying for each column in \code{x} #' in order, which column in \code{y} must be used to pair it with (use \code{0} #' to skip a column in \code{x}). The third option is to explicitly specify the #' columns to be matched using \code{pair_x} and \code{pair_y}. #' #' #' @section Note: #' Gower (1971) originally defined a similarity measure (\eqn{s}, say) #' with values ranging from 0 (completely dissimilar) to 1 (completely similar). #' The distance returned here equals \eqn{1-s}. #' #' #' @param x \code{[data.frame]} #' @param y \code{[data.frame]} #' @param pair_x \code{[numeric|character] (optional)} Columns in \code{x} used for comparison. #' See Details below. #' @param pair_y \code{[numeric|character] (optional)} Columns in \code{y} used for comparison. #' See Details below. #' @param eps \code{[numeric] (optional)} Computed numbers (variable ranges) #' smaller than \code{eps} are treated as zero. #' @param weights \code{[numeric] (optional)} A vector of weights of length \code{ncol(x)} #' that defines the weight applied to each component of the gower distance. #' @param ignore_case \code{[logical]} Toggle ignore case when neither \code{pair_x} #' nor \code{pair_y} are user-defined. #' @param nthread Number of threads to use for parallelization. By default, #' for a dual-core machine, 2 threads are used. For any other machine #' n-1 cores are used so your machine doesn't freeze during a big computation. #' The maximum nr of threads are determined using \code{omp_get_max_threads} at C level. #' #' #' @return #' A \code{numeric} vector of length \code{max(nrow(x),nrow(y))}. #' When there are no columns to compare, a message is printed and both #' \code{numeric(0)} is returned invisibly. #' #' @seealso \code{\link{gower_topn}} #' #' @references #' Gower, John C. "A general coefficient of similarity and some of its #' properties." Biometrics (1971): 857-871. #' #' @export gower_dist <- function(x, y, pair_x=NULL, pair_y=NULL, eps = 1e-8, weights=NULL, ignore_case=FALSE, nthread=getOption("gd_num_thread")){ check_recycling(nrow(x),nrow(y)) gower_work(x=x,y=y,pair_x=pair_x,pair_y=pair_y , n=NULL, eps=eps, weights=weights, ignore_case=ignore_case, nthread=nthread) } #' Find the top-n matches #' #' @description #' #' Find the top-n matches in \code{y} for each record in \code{x}. #' #' @inheritParams gower_dist #' @param n The top-n indices and distances to return. #' #' @seealso \code{\link{gower_dist}} #' #' @return #' A \code{list} with two array elements: \code{index} #' and \code{distance}. Both have size \code{n X nrow(x)}. Each ith column #' corresponds to the top-n best matches of \code{x} with rows in \code{y}. #' When there are no columns to compare, a message is printed and both #' \code{distance} and \code{index} will be empty matrices; the list is #' then returned invisibly. #' #' @examples #' # find the top 4 best matches in the iris data set with itself. #' x <- iris[1:3,] #' lookup <- iris[1:10,] #' gower_topn(x=x,y=lookup,n=4) #' #' #' @export gower_topn <- function(x, y, pair_x=NULL, pair_y = NULL, n=5, eps=1e-8, weights = NULL, ignore_case=FALSE, nthread=getOption("gd_num_thread")){ gower_work(x=x,y=y,pair_x=pair_x,pair_y=pair_y , n=n, eps=eps, weights=weights, ignore_case=ignore_case, nthread=nthread) } gower_work <- function(x, y, pair_x, pair_y, n, eps, weights, ignore_case, nthread){ stopifnot(is.numeric(eps), eps>0) if (is.null(pair_x) & is.null(pair_y)){ xnames <- if(ignore_case) toupper(names(x)) else names(x) ynames <- if(ignore_case) toupper(names(y)) else names(y) pair <- match(xnames, ynames, nomatch = 0L) } else if (is.null(pair_x)){ pair <- pair_y } else { if (is.character(pair_x) & is.character(pair_y)){ m <- match(names(x),pair_x,nomatch=0) pair_x <- pair_x[m] pair_y <- pair_y[m] } pair <- numeric(ncol(x)) pair[pair_x] <- pair_y } if ( !any(pair > 0) ){ message("Nothing to compare") return( if (is.null(n)){ # gower_dist invisible(numeric(0)) } else { # gower_topn invisible(list(distance=matrix(0)[0,0],index=matrix(0L)[0,0])) } ) } if ( !is.null(weights) && ( any( weights < 0 ) || !all(is.finite(weights)) ) ){ stop("At least one element of 'weights' is not a finite nonnegative number" , call. = FALSE) } if ( !is.null(weights) && length(weights) < length(pair) ){ msg <- sprintf("%d weights specified, expected %d" , length(weights), length(pair)) stop(msg, call. = FALSE) } # If the user didn't pass any weights, then weight all components of the # distance equally. if (is.null(weights)) weights <- rep(1, ncol(x)) # check column classes nthread <- as.integer(nthread) ranges <- numeric(length(pair)) for ( i in seq_along(pair)){ if (pair[i] == 0 ) next ranges[i] <- .Call("R_get_xy_range",x[[i]],y[[pair[i]]],nthread) } factor_x <- sapply(x,is.factor) factor_y <- sapply(y,is.factor) for ( i in seq_along(pair) ){ if ( pair[i] == 0 ) next iy <- pair[i] if (!factor_x[i] & !factor_y[iy]) next if ( factor_x[i] && !factor_y[iy] ){ stop("Column ", i, " of x is of class factor while matching column " , pair[i]," of y is of class ", class(y[[iy]]) ) } if ( !factor_x[i] && factor_y[iy] ){ stop("Column ", i, " of x is of class ", class(x[[i]]), " while matching column " , pair[i]," of y is of class factor" ) } if (factor_x[i] && factor_y[iy]){ if ( !isTRUE( all.equal( levels(x[[i]]), levels(y[[iy]]) ) ) ){ stop("Levels in column ", i, " of x do not match those of column ", pair[i], " in y.") } } } factor_pair <- as.integer(factor_x) eps <- as.double(eps) # translate to C-indices (base-0). pair <- as.integer(pair-1L) if (is.null(n)){ .Call("R_gower", x, y , ranges, pair, factor_pair, eps, weights, nthread) } else { L <- .Call("R_gower_topn", x, y, ranges, pair, factor_pair, as.integer(n), eps, weights, nthread) names(L) <- c("index","distance") dim(L$index) <- c(n,nrow(x)) dim(L$distance) <- dim(L$index) dimnames(L$index) <- list(topn=NULL,row=NULL) dimnames(L$distance) <- dimnames(L$index) L } } RECYCLEWARNING <- tryCatch(1:3+1:2,warning=function(e) e$message) check_recycling <- function(nx,ny){ mx <- max(nx,ny) mn <- min(nx,ny) if ((mx %% mn) != 0) warning(RECYCLEWARNING, call.=FALSE) } gower/vignettes/0000755000176200001440000000000013466614147013421 5ustar liggesusersgower/vignettes/intro.Rnw0000644000176200001440000001144113452644704015242 0ustar liggesusers%\VignetteIndexEntry{Introduction to the gower package} \documentclass[11pt]{article} \usepackage{enumitem} \setlist{nosep} \usepackage{hyperref} \hypersetup{ pdfborder={0 0 0} , colorlinks=true , urlcolor=red , linkcolor=blue } \renewcommand{\familydefault}{\sfdefault} \setlength{\parindent}{0pt} \setlength{\parskip}{2ex} \title{Introduction to the gower package} \author{Mark van der Loo} \newcommand{\code}[1]{\texttt{#1}} \newcommand{\pkg}[1]{\textbf{#1}} \begin{document} \maketitle{} \tableofcontents{} <>= options(prompt=" ") @ \newpage \section{Gower's distance measure} Gower's distance can be used to measure how different two records are. The records may contain combinations of logical, numerical, categorical or text data. The distance is always a number between 0 (identical) and 1 (maximally dissimilar). An easy to read specification of the measure is given in the original paper. Gower (1971) \href{http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.412.4155&rep=rep1&type=pdf}{A general coefficient of similarity and some of its properties}. \emph{Biometrics} **27** 857--874. In short, Gower's distance (or similarity) first computes distances between pairs of variables over two data sets and then combines those distances to a single value per record-pair. This package modifies Gower's original similarity measure in the following ways. \begin{itemize} \item{In stead of the original similarity $S$, the package returns the distance $1-S$.} \item{The original paper does not mention the concept of \code{NA}. Missing variables are skipped when computing the distance.} \item{The original paper does not mention character data. These are treated as categorical data.} \end{itemize} \section{Computing Gower's distance} The function \code{gower\_dist} computes pairwise-distances between records. <<>>= library(gower) dat1 <- iris[1:10,] dat2 <- iris[6:15,] gower_dist(dat1, dat2) @ If one data frame has less records than the other, the shortest one is recycled over (just like when you're adding two vectors of unequal length) <<>>= gower_dist(iris[1,], dat1) @ It is possible to control how columns from the two data sets are paired for comparison using the \code{pair\_x} and \code{pair\_y} arguments. This comes in handy when similar colums have different names accross datasets. By default, columns with matching names are paired. The behaviour is somewhat similar to that of base R's \code{merge} in that respect. <<>>= dat1 <- dat2 <- iris[1:10,] names(dat2) <- tolower(names(dat2)) gower_dist(dat1, dat2) # tell gower_dist to match columns 1..5 in dat1 with column 1..5 in dat2 gower_dist(dat1, dat2, pair_y=1:5) @ It is also possible to explicitly ignore case when matching columns by name. <<>>= gower_dist(dat1, dat2, ignore_case=TRUE) @ \section{Computing the top-n best matches} The function \code{gower\_topn} returns a list with two arrays. <<>>= dat1 <- iris[1:10,] L <- gower_topn(x=dat1, y=iris, n=3) L @ The first array is called \code{index}. Each column corresponds to one row of \code{x}. The entries of each column index the top $n$ best matches of that row in \code{x} with rows in \code{y}. In this example, the best match of the first row of \code{dat1} is record number \Sexpr{L$index[1,1]} from \code{iris} (this should be obvious, since they are the same record). The second best match is record number \Sexpr{L$index[2,1]} from \code{iris}. The second array is called \code{distance} and it contains the corresponding distances. \section{Using weights} Gower's distance is computed as an average over differences between variables. By setting \code{weights} you can compute the distance as a weighted average. <<>>= gower_dist(women[1,], women) gower_dist(women[1,], women, weights=c(2,3)) @ \section{Parallelization, memory usage} The underlying algorithm is implemented in C and parallelized using \href{http://www.openmp.org}{OpenMP}. OpenMP is available on most systems that can run R. Please see \href{https://cran.r-project.org/doc/manuals/r-release/R-exts.html#OpenMP-support}{this section} of the writing R extensions manual for up-to-details details on which systems are supported. At the time of writing (spring 2019), OSX is the only system not supporting OpenMP out of the box. You can still make it work by installing the gcc toolchain and compiling the package (and R). If OpenMP is not supported, the package will still work but the core algorithms will not be parallelized. This implementation makes no copies of the data in memory. When computing \code{gower\_dist}, two double precision arrays of size \code{max(nrow(x),nrow(y))} are kept in memory to store intermediate results. When computing the top-n matches, for $k$ cores, $k+2$ double precision arrays of length \code{nrow(y)} are created to store intermediate results at C level. \end{document} gower/MD50000644000176200001440000000161313466626147011725 0ustar liggesusers703fa7b18dfdf642d69ffc834777867c *DESCRIPTION 83404f04f998736f089f40b74968e0a3 *NAMESPACE 45b71ba161637bc146b656e7292bcb01 *NEWS 2a15d8f245c2f6d3cd49f98d1c760bbd *R/gower-pkg.R eaf7f1e6685d67e053b7d87142db4a7d *R/gower.R 9da2ad93e5c104057631a525e0715c81 *build/vignette.rds b54853011026a0f34882fc97a62ac44b *inst/doc/intro.R b69562b9ebfbf47bbc317ec4ddc75bed *inst/doc/intro.Rnw dca6f4c9b3d11f9e9443063c51f44a4a *inst/doc/intro.pdf 03ea67ff7f254975bfd511ad8a395449 *inst/tinytest/test_gower.R 68b9193cbb24435b2ecb773b97b23ccb *man/gower-package.Rd afa5eb47fa911ccd0fc732394197f289 *man/gower_dist.Rd ceca01be878cd5500dc7df08b2a6e99a *man/gower_topn.Rd 4e95da77024f1ca60e63ce4aabf063c1 *src/Makevars 9669dc7ac1254dc2a7933580cf561bb8 *src/R_register_native.c 0e1f6b5670426ee21375974d26aec433 *src/gower.c 4dbc149411df0021bb5e262551d45e28 *tests/tinytest.R b69562b9ebfbf47bbc317ec4ddc75bed *vignettes/intro.Rnw gower/build/0000755000176200001440000000000013466614147012510 5ustar liggesusersgower/build/vignette.rds0000644000176200001440000000032713466614147015051 0ustar liggesusersmP0 QHLL_ ׅ\č_.#%ڞtbCh0 qυV2Dk][>CTTTBKTk-BcrA>[AYJ5r&5P㦼qotpW?txE6ƅB~5gower/DESCRIPTION0000644000176200001440000000151613466626147013125 0ustar liggesusersPackage: gower Maintainer: Mark van der Loo License: GPL-3 Title: Gower's Distance LazyData: no Type: Package LazyLoad: yes Authors@R: c( person("Mark", "van der Loo", role=c("aut","cre"),email="mark.vanderloo@gmail.com") , person("David", "Turner", role="ctb")) Description: Compute Gower's distance (or similarity) coefficient between records. Compute the top-n matches between records. Core algorithms are executed in parallel on systems supporting OpenMP. Version: 0.2.1 URL: https://github.com/markvanderloo/gower BugReports: https://github.com/markvanderloo/gower/issues Suggests: tinytest (>= 0.9.3), RoxygenNote: 6.1.1 NeedsCompilation: yes Packaged: 2019-05-14 19:35:03 UTC; mark Author: Mark van der Loo [aut, cre], David Turner [ctb] Repository: CRAN Date/Publication: 2019-05-14 21:00:23 UTC gower/man/0000755000176200001440000000000013452644704012161 5ustar liggesusersgower/man/gower_dist.Rd0000644000176200001440000000503113452644704014615 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/gower.R \name{gower_dist} \alias{gower_dist} \title{Gower's distance} \usage{ gower_dist(x, y, pair_x = NULL, pair_y = NULL, eps = 1e-08, weights = NULL, ignore_case = FALSE, nthread = getOption("gd_num_thread")) } \arguments{ \item{x}{\code{[data.frame]}} \item{y}{\code{[data.frame]}} \item{pair_x}{\code{[numeric|character] (optional)} Columns in \code{x} used for comparison. See Details below.} \item{pair_y}{\code{[numeric|character] (optional)} Columns in \code{y} used for comparison. See Details below.} \item{eps}{\code{[numeric] (optional)} Computed numbers (variable ranges) smaller than \code{eps} are treated as zero.} \item{weights}{\code{[numeric] (optional)} A vector of weights of length \code{ncol(x)} that defines the weight applied to each component of the gower distance.} \item{ignore_case}{\code{[logical]} Toggle ignore case when neither \code{pair_x} nor \code{pair_y} are user-defined.} \item{nthread}{Number of threads to use for parallelization. By default, for a dual-core machine, 2 threads are used. For any other machine n-1 cores are used so your machine doesn't freeze during a big computation. The maximum nr of threads are determined using \code{omp_get_max_threads} at C level.} } \value{ A \code{numeric} vector of length \code{max(nrow(x),nrow(y))}. When there are no columns to compare, a message is printed and both \code{numeric(0)} is returned invisibly. } \description{ Compute Gower's distance, pairwise between records in two data sets \code{x} and \code{y}. Records from the smallest data set are recycled over. } \section{Details}{ There are three ways to specify which columns of \code{x} should be compared with what columns of \code{y}. The first option is do give no specification. In that case columns with matching names will be used. The second option is to use only the \code{pairs_y} argument, specifying for each column in \code{x} in order, which column in \code{y} must be used to pair it with (use \code{0} to skip a column in \code{x}). The third option is to explicitly specify the columns to be matched using \code{pair_x} and \code{pair_y}. } \section{Note}{ Gower (1971) originally defined a similarity measure (\eqn{s}, say) with values ranging from 0 (completely dissimilar) to 1 (completely similar). The distance returned here equals \eqn{1-s}. } \references{ Gower, John C. "A general coefficient of similarity and some of its properties." Biometrics (1971): 857-871. } \seealso{ \code{\link{gower_topn}} } gower/man/gower_topn.Rd0000644000176200001440000000374213452644704014641 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/gower.R \name{gower_topn} \alias{gower_topn} \title{Find the top-n matches} \usage{ gower_topn(x, y, pair_x = NULL, pair_y = NULL, n = 5, eps = 1e-08, weights = NULL, ignore_case = FALSE, nthread = getOption("gd_num_thread")) } \arguments{ \item{x}{\code{[data.frame]}} \item{y}{\code{[data.frame]}} \item{pair_x}{\code{[numeric|character] (optional)} Columns in \code{x} used for comparison. See Details below.} \item{pair_y}{\code{[numeric|character] (optional)} Columns in \code{y} used for comparison. See Details below.} \item{n}{The top-n indices and distances to return.} \item{eps}{\code{[numeric] (optional)} Computed numbers (variable ranges) smaller than \code{eps} are treated as zero.} \item{weights}{\code{[numeric] (optional)} A vector of weights of length \code{ncol(x)} that defines the weight applied to each component of the gower distance.} \item{ignore_case}{\code{[logical]} Toggle ignore case when neither \code{pair_x} nor \code{pair_y} are user-defined.} \item{nthread}{Number of threads to use for parallelization. By default, for a dual-core machine, 2 threads are used. For any other machine n-1 cores are used so your machine doesn't freeze during a big computation. The maximum nr of threads are determined using \code{omp_get_max_threads} at C level.} } \value{ A \code{list} with two array elements: \code{index} and \code{distance}. Both have size \code{n X nrow(x)}. Each ith column corresponds to the top-n best matches of \code{x} with rows in \code{y}. When there are no columns to compare, a message is printed and both \code{distance} and \code{index} will be empty matrices; the list is then returned invisibly. } \description{ Find the top-n matches in \code{y} for each record in \code{x}. } \examples{ # find the top 4 best matches in the iris data set with itself. x <- iris[1:3,] lookup <- iris[1:10,] gower_topn(x=x,y=lookup,n=4) } \seealso{ \code{\link{gower_dist}} } gower/man/gower-package.Rd0000644000176200001440000000040213452644704015160 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/gower-pkg.R \docType{package} \name{gower-package} \alias{gower-package} \title{Gower's distance/similarity measure.} \description{ A C-based implementation of Gower's distance. }