doRNG/0000755000176200001440000000000013613501566011231 5ustar liggesusersdoRNG/NAMESPACE0000644000176200001440000000041613612460574012453 0ustar liggesusers# Generated by roxygen2: do not edit by hand export("%dorng%") export(doRNGversion) export(registerDoRNG) import(foreach) import(rngtools) import(stats) importFrom(iterators,iter) importFrom(utils,compareVersion) importFrom(utils,head) importFrom(utils,packageVersion) doRNG/demo/0000755000176200001440000000000013556560424012161 5ustar liggesusersdoRNG/demo/00Index0000644000176200001440000000006413556341614013311 0ustar liggesusersdoRNG Some features of the %dorng% foreach operator doRNG/demo/doRNG.R0000644000176200001440000000257513556560424013266 0ustar liggesuserslibrary(doRNG) library(doParallel) if( .Platform$OS.type == "unix" ){ registerDoParallel(2) # single %dorng% loops are reproducible r1 <- foreach(i=1:4, .options.RNG=1234) %dorng% { runif(1) } r2 <- foreach(i=1:4, .options.RNG=1234) %dorng% { runif(1) } identical(r1, r2) # the sequence os RNG seed is stored as an attribute attr(r1, 'rng') # sequences of %dorng% loops are reproducible set.seed(1234) s1 <- foreach(i=1:4) %dorng% { runif(1) } s2 <- foreach(i=1:4) %dorng% { runif(1) } # two consecutive (unseed) %dorng% loops are not identical identical(s1, s2) # But the whole sequence of loops is reproducible set.seed(1234) s1.2 <- foreach(i=1:4) %dorng% { runif(1) } s2.2 <- foreach(i=1:4) %dorng% { runif(1) } identical(s1, s1.2) && identical(s2, s2.2) # it gives the same result as with .options.RNG identical(r1, s1) } # Works with SNOW-like and MPI clusters # SNOW-like cluster cl <- makeCluster(2) registerDoParallel(cl) s1 <- foreach(i=1:4, .options.RNG=1234) %dorng% { runif(1) } s2 <- foreach(i=1:4, .options.RNG=1234) %dorng% { runif(1) } identical(s1, s2) stopCluster(cl) registerDoSEQ() # MPI cluster library(doMPI) cl <- startMPIcluster(2) registerDoMPI(cl) s1 <- foreach(i=1:4, .options.RNG=1234) %dorng% { runif(1) } s2 <- foreach(i=1:4, .options.RNG=1234) %dorng% { runif(1) } identical(s1, s2) closeCluster(cl) registerDoSEQ() doRNG/.Rinstignore0000644000176200001440000000002713556341614013536 0ustar liggesusersvignettes/cleveref.sty doRNG/man/0000755000176200001440000000000013612460574012006 5ustar liggesusersdoRNG/man/doRNG-package.Rd0000644000176200001440000000524213612460574014642 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/doRNG-package.R \docType{package} \encoding{UTF-8} \name{doRNG-package} \alias{doRNG-package} \title{Generic Reproducible Parallel Backend for foreach Loops} \description{ The \emph{doRNG} package provides functions to perform reproducible parallel foreach loops, using independent random streams as generated by L'Ecuyer's combined multiple-recursive generator [L'Ecuyer (1999)]. It enables to easily convert standard %dopar% loops into fully reproducible loops, independently of the number of workers, the task scheduling strategy, or the chosen parallel environment and associated foreach backend. It has been tested with the following foreach backend: doMC, doSNOW, doMPI. } \examples{ # register parallel backend library(doParallel) cl <- makeCluster(2) registerDoParallel(cl) ## standard \%dopar\% loop are not reproducible set.seed(123) r1 <- foreach(i=1:4) \%dopar\%{ runif(1) } set.seed(123) r2 <- foreach(i=1:4) \%dopar\%{ runif(1) } identical(r1, r2) \dontshow{ stopifnot(!identical(r1, r2)) } ## \%dorng\% loops _are_ reproducible set.seed(123) r1 <- foreach(i=1:4) \%dorng\%{ runif(1) } set.seed(123) r2 <- foreach(i=1:4) \%dorng\%{ runif(1) } identical(r1, r2) \dontshow{ stopifnot(identical(r1, r2)) } # alternative way of seeding a1 <- foreach(i=1:4, .options.RNG=123) \%dorng\%{ runif(1) } a2 <- foreach(i=1:4, .options.RNG=123) \%dorng\%{ runif(1) } identical(a1, a2) && identical(a1, r1) \dontshow{ stopifnot(identical(a1, a2) && identical(a1, r1)) } ## sequences of \%dorng\% loops _are_ reproducible set.seed(123) s1 <- foreach(i=1:4) \%dorng\%{ runif(1) } s2 <- foreach(i=1:4) \%dorng\%{ runif(1) } identical(s1, r1) && !identical(s1, s2) \dontshow{ stopifnot(identical(s1, r1) && !identical(s1, s2)) } set.seed(123) s1.2 <- foreach(i=1:4) \%dorng\%{ runif(1) } s2.2 <- foreach(i=1:4) \%dorng\%{ runif(1) } identical(s1, s1.2) && identical(s2, s2.2) \dontshow{ stopifnot(identical(s1, s1.2) && identical(s2, s2.2)) } ## Non-invasive way of converting \%dopar\% loops into reproducible loops registerDoRNG(123) s3 <- foreach(i=1:4) \%dopar\%{ runif(1) } s4 <- foreach(i=1:4) \%dopar\%{ runif(1) } identical(s3, s1) && identical(s4, s2) \dontshow{ stopifnot(identical(s3, s1) && identical(s4, s2)) } stopCluster(cl) } \references{ L'Ecuyer P (1999). “Good parameters and implementations for combined multiple recursive random number generators.” _Operations Research_, *47*(1). doi: 10.1287/opre.47.1.159 (URL: https://doi.org/10.1287/opre.47.1.159). } \seealso{ \code{\link{doRNG}}, \code{\link{RNGseq}} } \author{ \strong{Maintainer}: Renaud Gaujoux \email{renozao@protonmail.com} } \keyword{package} doRNG/man/grapes-dorng-grapes.Rd0000644000176200001440000000401013612460574016137 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/doRNG.R \name{\%dorng\%} \alias{\%dorng\%} \title{Reproducible Parallel Foreach Backend} \usage{ obj \%dorng\% ex } \arguments{ \item{obj}{a foreach object as returned by a call to \code{\link{foreach}}.} \item{ex}{the \code{R} expression to evaluate.} } \value{ \code{\%dorng\%} returns the result of the foreach loop. See \code{\link{\%dopar\%}}. The whole sequence of RNG seeds is stored in the result object as an attribute. Use \code{attr(res, 'rng')} to retrieve it. } \description{ \code{\%dorng\%} is a foreach operator that provides an alternative operator \code{\%dopar\%}, which enable reproducible foreach loops to be performed. } \section{Global options}{ These options are for advanced users that develop `foreach backends: * 'doRNG.rng_change_warning_skip': if set to a single logical `FALSE/TRUE`, it indicates whether a warning should be thrown if the RNG seed is changed by the registered parallel backend (default=FALSE). Set it to `TRUE` if you know that running your backend will change the RNG state and want to disable the warning. This option can also be set to a character vector that specifies the name(s) of the backend(s) for which the warning should be skipped. } \examples{ library(doParallel) cl <- makeCluster(2) registerDoParallel(cl) # standard \%dopar\% loops are _not_ reproducible set.seed(1234) s1 <- foreach(i=1:4) \%dopar\% { runif(1) } set.seed(1234) s2 <- foreach(i=1:4) \%dopar\% { runif(1) } identical(s1, s2) # single \%dorng\% loops are reproducible r1 <- foreach(i=1:4, .options.RNG=1234) \%dorng\% { runif(1) } r2 <- foreach(i=1:4, .options.RNG=1234) \%dorng\% { runif(1) } identical(r1, r2) # the sequence os RNG seed is stored as an attribute attr(r1, 'rng') # stop cluster stopCluster(cl) # More examples can be found in demo `doRNG` \dontrun{ demo('doRNG') } } \seealso{ \code{\link{foreach}}, \code{\link[doParallel]{doParallel}} , \code{\link[doParallel]{registerDoParallel}}, \code{\link[doMPI]{doMPI}} } doRNG/man/infoDoRNG.Rd0000644000176200001440000000177013612460574014067 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/doRNG.R \name{infoDoRNG} \alias{infoDoRNG} \alias{doRNG} \title{Getting Information About doRNG Foreach Backend} \usage{ infoDoRNG(data, item) doRNG(obj, ex, envir, data) } \arguments{ \item{data}{configuration data of the doRNG backend} \item{item}{the data item requested, as a character string (e.g. 'name', 'workers', 'version')} \item{obj}{a foreach description of the loop arguments} \item{ex}{the lopp expression} \item{envir}{the loop's evaluation environment} } \value{ \code{infoDoRNG} returns the requested info (usually as a character string or a numeric value). } \description{ \code{infoDoRNG} returns information about the doRNG backend, e.g., version, number of workers. It is not meant to be called by the user. } \section{Functions}{ \itemize{ \item \code{doRNG}: implements the generic reproducible foreach backend. It should not be called directly by the user. }} \author{ Renaud Gaujoux } \keyword{internal} doRNG/man/doRNGversion.Rd0000644000176200001440000000450113612460574014654 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/doRNG.R \name{doRNGversion} \alias{doRNGversion} \title{Back Compatibility Option for doRNG} \usage{ doRNGversion(x) } \arguments{ \item{x}{version number to switch to, or missing to get the currently active version number, or \code{NULL} to reset to the default behaviour, i.e. of the latest version.} } \value{ a character string If \code{x} is missing this function returns the version number from the current behaviour. If \code{x} is specified, the function returns the old value of the version number (invisible). } \description{ Sets the behaviour of \%dorng\% foreach loops from a given version number. } \section{Behaviour changes in versions}{ \describe{ \item{1.4}{ The behaviour of \code{doRNGseed}, and therefore of \code{\%dorng\%} loops, changed in the case where the current RNG was L'Ecuyer-CMRG. Using \code{set.seed} before a non-seeded loop used not to be identical to seeding via \code{.options.RNG}. Another bug was that non-seeded loops would share most of their RNG seed! } \item{1.7.4}{Prior to this version, in the case where the RNG had not been called yet, the first seeded \code{\%dorng\%} loops would not give the identical results as subsequent loops despite using the same seed (see \url{https://github.com/renozao/doRNG/issues/12}). This has been fixed in version 1.7.4, where the RNG is called once (\code{sample(NA)}), whenever the .Random.seed is not found in global environment. } } } \examples{ \dontshow{ registerDoSEQ() } ## Seeding when current RNG is L'Ecuyer-CMRG RNGkind("L'Ecuyer") doRNGversion("1.4") # in version >= 1.4 seeding behaviour changed to fix a bug set.seed(123) res <- foreach(i=1:3) \%dorng\% runif(1) res2 <- foreach(i=1:3) \%dorng\% runif(1) stopifnot( !identical(attr(res, 'rng')[2:3], attr(res2, 'rng')[1:2]) ) res3 <- foreach(i=1:3, .options.RNG=123) \%dorng\% runif(1) stopifnot( identical(res, res3) ) # buggy behaviour in version < 1.4 doRNGversion("1.3") res <- foreach(i=1:3) \%dorng\% runif(1) res2 <- foreach(i=1:3) \%dorng\% runif(1) stopifnot( identical(attr(res, 'rng')[2:3], attr(res2, 'rng')[1:2]) ) res3 <- foreach(i=1:3, .options.RNG=123) \%dorng\% runif(1) stopifnot( !identical(res, res3) ) # restore default RNG RNGkind("default") # restore to current doRNG version doRNGversion(NULL) } doRNG/man/registerDoRNG.Rd0000644000176200001440000000477513556560424014772 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/doRNG.R \name{registerDoRNG} \alias{registerDoRNG} \title{Registering doRNG for Persistent Reproducible Parallel Foreach Loops} \usage{ registerDoRNG(seed = NULL, once = TRUE) } \arguments{ \item{seed}{a numerical seed to use (as a single or 6-length numerical value)} \item{once}{a logical to indicate if the RNG sequence should be seeded at the beginning of each loop or only at the first loop.} } \description{ \code{registerDoRNG} registers the doRNG foreach backend. Subsequent \%dopar\% loops are then performed using the previously registered foreach backend, but are internally performed as \code{\link{\%dorng\%}} loops, making them fully reproducible. } \details{ Briefly, the RNG is set, before each iteration, with seeds for L'Ecuyer's CMRG that overall generate a reproducible sequence of statistically independent random streams. Note that (re-)registering a foreach backend other than doRNG, after a call to \code{registerDoRNG} disables doRNG -- which then needs to be registered. } \examples{ library(doParallel) cl <- makeCluster(2) registerDoParallel(cl) # One can make reproducible loops using the \%dorng\% operator r1 <- foreach(i=1:4, .options.RNG=1234) \%dorng\% { runif(1) } # or convert \%dopar\% loops using registerDoRNG registerDoRNG(1234) r2 <- foreach(i=1:4) \%dopar\% { runif(1) } identical(r1, r2) stopCluster(cl) # Registering another foreach backend disables doRNG cl <- makeCluster(2) registerDoParallel(cl) set.seed(1234) s1 <- foreach(i=1:4) \%dopar\% { runif(1) } set.seed(1234) s2 <- foreach(i=1:4) \%dopar\% { runif(1) } identical(s1, s2) \dontshow{ stopifnot(!identical(s1, s2)) } # doRNG is re-nabled by re-registering it registerDoRNG() set.seed(1234) r3 <- foreach(i=1:4) \%dopar\% { runif(1) } identical(r2, r3) # NB: the results are identical independently of the task scheduling # (r2 used 2 nodes, while r3 used 3 nodes) # argument `once=FALSE` reseeds doRNG's seed at the beginning of each loop registerDoRNG(1234, once=FALSE) r1 <- foreach(i=1:4) \%dopar\% { runif(1) } r2 <- foreach(i=1:4) \%dopar\% { runif(1) } identical(r1, r2) # Once doRNG is registered the seed can also be passed as an option to \%dopar\% r1.2 <- foreach(i=1:4, .options.RNG=456) \%dopar\% { runif(1) } r2.2 <- foreach(i=1:4, .options.RNG=456) \%dopar\% { runif(1) } identical(r1.2, r2.2) && !identical(r1.2, r1) \dontshow{ stopifnot(identical(r1.2, r2.2) && !identical(r1.2, r1)) } stopCluster(cl) } \seealso{ \code{\link{\%dorng\%}} } doRNG/DESCRIPTION0000644000176200001440000000235713613501566012746 0ustar liggesusersPackage: doRNG Type: Package Title: Generic Reproducible Parallel Backend for 'foreach' Loops Version: 1.8.2 Encoding: UTF-8 Authors@R: person("Renaud", "Gaujoux", email = "renozao@protonmail.com", role = c("aut", "cre")) Description: Provides functions to perform reproducible parallel foreach loops, using independent random streams as generated by L'Ecuyer's combined multiple-recursive generator [L'Ecuyer (1999), ]. It enables to easily convert standard %dopar% loops into fully reproducible loops, independently of the number of workers, the task scheduling strategy, or the chosen parallel environment and associated foreach backend. License: GPL (>= 2) LazyLoad: yes URL: https://renozao.github.io/doRNG BugReports: http://github.com/renozao/doRNG/issues VignetteBuilder: knitr Depends: R (>= 3.0.0), foreach, rngtools (>= 1.5) Imports: stats, utils, iterators Suggests: doParallel, doMPI, doRedis, rbenchmark, devtools, knitr, bibtex, testthat, pkgmaker (>= 0.31) RoxygenNote: 7.0.2 NeedsCompilation: no Packaged: 2020-01-26 15:58:10 UTC; renaud Author: Renaud Gaujoux [aut, cre] Maintainer: Renaud Gaujoux Repository: CRAN Date/Publication: 2020-01-27 06:30:14 UTC doRNG/build/0000755000176200001440000000000013613333422012322 5ustar liggesusersdoRNG/build/vignette.rds0000644000176200001440000000037013613333422014661 0ustar liggesusersmQMk0 U> v/ȯ(a0B`W-V[ N _Niz3H'Apll6BHND[ ':>= pkgmaker::latex_preamble() @ % REFERENCES \usepackage[minnames=1,maxnames=2,backend=bibtex]{biblatex} \AtEveryCitekey{\clearfield{url}} <>= pkgmaker::latex_bibliography('doRNG') @ \newcommand{\citet}[1]{\citeauthor{#1}~\cite{#1}} %% \newcommand{\graphwidth}{0.9\columnwidth} % clever references \usepackage[noabbrev, capitalise, nameinlink]{cleveref} \newcommand{\dorng}{\code{\%dorng\%}\xspace} \title{Using the \code{doRNG} package\\ {\small \Rpkg{doRNG} -- Version \Sexpr{packageVersion('doRNG')}}} \author{Renaud Gaujoux} \begin{document} \maketitle \tableofcontents \section*{Introduction} \addcontentsline{toc}{section}{Introduction} Research reproducibility is an issue of concern, e.g. in bioinformatics \cite{Hothorn2011,Stodden2011,Ioannidis2008}. Some analyses require multiple independent runs to be performed, or are amenable to a split-and-reduce scheme. For example, some optimisation algorithms are run multiple times from different random starting points, and the result that achieves the least approximation error is selected. The \citeCRANpkg{foreach} provides a very convenient way to perform parallel computations, with different parallel environments such as MPI or Redis, using a transparent loop-like syntax: <>= options(width=90) library(pkgmaker) library(knitr) opts_chunk$set(size = "footnotesize") knit_hooks$set(try = pkgmaker::hook_try) @ <>= # load and register parallel backend for multicore computations library(doParallel) cl <- makeCluster(2) registerDoParallel(cl) # perform 5 tasks in parallel x <- foreach(i=1:5) %dopar% { i + runif(1) } unlist(x) @ For each parallel environment a \emph{backend} is implemented as a specialised \code{\%dopar\%} operator, which performs the setup and pre/post-processing specifically required by the environment (e.g. export of variable to each worker). The \code{foreach} function and the \code{\%dopar\%} operator handle the generic parameter dispatch when the task are split between worker processes, as well as the reduce step -- when the results are returned to the master worker. When stochastic computations are involved, special random number generators must be used to ensure that the separate computations are indeed statistically independent -- unless otherwise wanted -- and that the loop is reproducible. In particular, standard \code{\%dopar\%} loops are not reproducible: <>= # with standard %dopar%: foreach loops are not reproducible set.seed(123) res <- foreach(i=1:5) %dopar% { runif(3) } set.seed(123) res2 <- foreach(i=1:5) %dopar% { runif(3) } identical(res, res2) @ A random number generator commonly used to achieve reproducibility is the combined multiple-recursive generator from \citet{Lecuyer1999}. This generator can generate independent random streams, from a 6-length numeric seed. The idea is then to generate a sequence of random stream of the same length as the number of iteration (i.e. tasks) and use a different stream when computing each one of them. The \citeCRANpkg{doRNG} provides convenient ways to implement reproducible parallel \code{foreach} loops, independently of the parallel backend used to perform the computation. We illustrate its use, showing how non-reproducible loops can be made reproducible, even when tasks are not scheduled in the same way in two separate set of runs, e.g. when the workers do not get to compute the same number of tasks or the number of workers is different. The package has been tested with the \CRANpkg*{doParallel} and \CRANpkg*{doMPI} packages \citepkg{Rpackage:doMPI,Rpackage:doParallel}, but should work with other backends such as provided by the \citeCRANpkg{doRedis}. \section{The \texttt{\%dorng\%} operator} The \Rpkg{doRNG} defines a new generic operator, \code{\%dorng\%}, to be used with foreach loops, instead of the standard {\%dopar\%}. Loops that use this operator are \emph{de facto} reproducible. <>= # load the doRNG package library(doRNG) # using %dorng%: loops _are_ reproducible set.seed(123) res <- foreach(i=1:5) %dorng% { runif(3) } set.seed(123) res2 <- foreach(i=1:5) %dorng% { runif(3) } identical(res, res2) @ \subsection{How it works} For a loop with $N$ iterations, the \code{\%dorng\%} operator internally performs the following tasks: \begin{enumerate} \item generate a sequence of random seeds $(S_i)_{1\leq i\leq N}$ for the \proglang{R} random number generator \code{"L'Ecuyer-CMRG"} \cite{Lecuyer1999}, using the function \code{nextRNGStream} from the \citeCRANpkg{parallel}, which ensure the different RNG streams are statistically independent; \item modify the loop's \proglang{R} expression so that the random number generator is set to \code{"L'Ecuyer-CMRG"} at the beginning of each iteration, and is seeded with consecutive seeds in $(S_n)$: iteration $i$ is seeded with $S_i$, $1\leq i\leq N$; \item call the standard \code{\%dopar\%} operator, which in turn calls the relevant (i.e. registered) foreach parallel backend; \item store the whole sequence of random seeds as an attribute in the result object: <>= attr(res, 'rng') @ \end{enumerate} \subsection{Seeding computations} Sequences of random streams for \code{"L'Ecuyer-CMRG"} are generated using a 6-length integer seed, e.g.,: <>= nextRNGStream(c(407L, 1:6)) @ However, the \code{\%dorng\%} operator provides alternative -- convenient -- ways of seeding reproducible loops. \begin{description} \item[\code{set.seed}:] as shown above, calling \code{set.seed} before the loop ensure reproducibility of the results, using a single integer as a seed. The actual 6-length seed is then generated with an internal call to \code{RNGkind("L'Ecuyer-CMRG")}. \item[\code{.options.RNG} with single integer:] the \dorng operator support options that can be passed in the \code{foreach} statement, containing arguments for the internal call to \code{set.seed}: <>= # use a single numeric as a seed s <- foreach(i=1:5, .options.RNG=123) %dorng% { runif(3) } s2 <- foreach(i=1:5, .options.RNG=123) %dorng% { runif(3) } identical(s, s2) @ \noindent \textbf{Note}: calling \code{set.seed} before the loop is equivalent to passing the seed in \code{.options.RNG}. See \cref{sec:set_seed} for more details. \medskip The kind of Normal generator may also be passed in \code{.options.RNG}: <>= ## Pass the Normal RNG kind to use within the loop # results are identical if not using the Normal kind in the loop optsN <- list(123, normal.kind="Ahrens") resN.U <- foreach(i=1:5, .options.RNG=optsN) %dorng% { runif(3) } identical(resN.U[1:5], res[1:5]) # Results are different if the Normal kind is used and is not the same resN <- foreach(i=1:5, .options.RNG=123) %dorng% { rnorm(3) } resN1 <- foreach(i=1:5, .options.RNG=optsN) %dorng% { rnorm(3) } resN2 <- foreach(i=1:5, .options.RNG=optsN) %dorng% { rnorm(3) } identical(resN[1:5], resN1[1:5]) identical(resN1[1:5], resN2[1:5]) @ \item[\code{.options.RNG} with 6-length:] the actual 6-length integer seed used for the first RNG stream may be passed via \code{options.RNG}: <>= # use a 6-length numeric s <- foreach(i=1:5, .options.RNG=1:6) %dorng% { runif(3) } attr(s, 'rng')[1:3] @ \item[\code{.options.RNG} with 7-length:] a 7-length integer seed may also be passed via \code{options.RNG}, which is useful to seed a loop with the value of \code{.Random.seed} as used in some iteration of another loop\footnote{Note that the RNG kind is then always required to be the \code{"L'Ecuyer-CMRG"}, i.e. the first element of the seed must have unit 7 (e.g. 407 or 107).}: <>= # use a 7-length numeric, used as first value for .Random.seed seed <- attr(res, 'rng')[[2]] s <- foreach(i=1:5, .options.RNG=seed) %dorng% { runif(3) } identical(s[1:4], res[2:5]) @ \item[\code{.options.RNG} with complete sequence of seeds:] the complete description of the sequence of seeds to be used may be passed via \code{options.RNG}, as a list or a matrix with the seeds in columns. This is useful to seed a loop exactly as desired, e.g. using an RNG other than \code{"L'Ecuyer-CMRG"}, or using different RNG kinds in each iteration, which probably have different seed length, in order to compare their stochastic properties. It also allows to reproduce \code{\%dorng\%} loops without knowing their seeding details: <>= # reproduce previous %dorng% loop s <- foreach(i=1:5, .options.RNG=res) %dorng% { runif(3) } identical(s, res) ## use completely custom sequence of seeds (e.g. using RNG "Marsaglia-Multicarry") # as a matrix seedM <- rbind(rep(401, 5), mapply(rep, 1:5, 2)) seedM sM <- foreach(i=1:5, .options.RNG=seedM) %dorng% { runif(3) } # same seeds passed as a list seedL <- lapply(seq(ncol(seedM)), function(i) seedM[,i]) sL <- foreach(i=1:5, .options.RNG=seedL) %dorng% { runif(3) } identical(sL, sM) @ \end{description} \subsection{Difference between \texttt{set.seed} and \texttt{.options.RNG}} \label{sec:set_seed} While it is equivalent to seed \dorng loops with \code{set.seed} and \code{.options.RNG}, it is important to note that the result depends on the current RNG kind \footnote{See \cref{sec:issues} about a bug in versions < 1.4 on this feature.}: <>= # default RNG kind RNGkind('default') def <- foreach(i=1:5, .options.RNG=123) %dorng% { runif(3) } # Marsaglia-Multicarry RNGkind('Marsaglia') mars <- foreach(i=1:5, .options.RNG=123) %dorng% { runif(3) } identical(def, mars) # revert to default RNG kind RNGkind('default') @ This is a ``normal'' behaviour, which is a side-effect of the expected equivalence between \code{set.seed} and \code{.options.RNG}. This should not be a problem for reproducibility though, as R RNGs are stable across versions, and loops are most of the time used with the default RNG settings. In order to ensure seeding is independent from the current RNG, one has to pass a 7-length numeric seed to \code{.options.RNG}, which is then used directly as a value for \code{.Random.seed} (see below). \section{Parallel environment independence} An important feature of \code{\%dorng\%} loops is that their result is independent of the underlying parallel physical settings. Two separate runs seeded with the same value will always produce the same results. Whether they use the same number of worker processes, parallel backend or task scheduling does not influence the final result. This also applies to computations performed sequentially with the \code{doSEQ} backend. The following code illustrates this feature using 2 or 3 workers. <>= # define a stochastic task to perform task <- function() c(pid=Sys.getpid(), val=runif(1)) # using the previously registered cluster with 2 workers set.seed(123) res_2workers <- foreach(i=1:5, .combine=rbind) %dorng% { task() } # stop cluster stopCluster(cl) # Sequential computation registerDoSEQ() set.seed(123) res_seq <- foreach(i=1:5, .combine=rbind) %dorng% { task() } # # Using 3 workers # NB: if re-running this vignette you should edit to force using 3 here cl <- makeCluster( if(isManualVignette()) 3 else 2) length(cl) # register new cluster registerDoParallel(cl) set.seed(123) res_3workers <- foreach(i=1:5, .combine=rbind) %dorng% { task() } # task schedule is different pid <- rbind(res1=res_seq[,1], res_2workers[,1], res2=res_3workers[,1]) storage.mode(pid) <- 'integer' pid # results are identical identical(res_seq[,2], res_2workers[,2]) && identical(res_2workers[,2], res_3workers[,2]) @ \section{Reproducible \texttt{\%dopar\%} loops} The \Rpkg{doRNG} also provides a non-invasive way to convert \code{\%dopar\%} loops into reproducible loops, i.e. without changing their actual definition. It is useful to quickly ensure the reproducibility of existing code or functions whose definition is not accessible (e.g. from other packages). This is achieved by registering the \code{doRNG} backend: <>= set.seed(123) res <- foreach(i=1:5) %dorng% { runif(3) } registerDoRNG(123) res_dopar <- foreach(i=1:5) %dopar% { runif(3) } identical(res_dopar, res) attr(res_dopar, 'rng') @ \section{Reproducibile sets of loops} Sequences of multiple loops are reproducible, whether using the \code{\%dorng\%} operator or the registered \code{doRNG} backend: <>= set.seed(456) s1 <- foreach(i=1:5) %dorng% { runif(3) } s2 <- foreach(i=1:5) %dorng% { runif(3) } # the two loops do not use the same streams: different results identical(s1, s2) # but the sequence of loops is reproducible as a whole set.seed(456) r1 <- foreach(i=1:5) %dorng% { runif(3) } r2 <- foreach(i=1:5) %dorng% { runif(3) } identical(r1, s1) && identical(r2, s2) # one can equivalently register the doRNG backend and use %dopar% registerDoRNG(456) r1 <- foreach(i=1:5) %dopar% { runif(3) } r2 <- foreach(i=1:5) %dopar% { runif(3) } identical(r1, s1) && identical(r2, s2) @ \section{Nested and conditional loops} \label{sec:nested} Nested and conditional foreach loops are currently not supported and generate an error: <>= # nested loop try( foreach(i=1:10) %:% foreach(j=1:i) %dorng% { rnorm(1) } ) # conditional loop try( foreach(i=1:10) %:% when(i %% 2 == 0) %dorng% { rnorm(1) } ) @ In this section, we propose a general work around for this kind of loops, that will eventually be incorporated in the \code{\%dorng\%} operator -- when I find out how to mimic its behaviour from the operator itself. \subsection{Nested loops} The idea is to create a sequence of RNG seeds before the outer loop, and use each of them successively to set the RNG in the inner loop -- which is exactly what \code{\%dorng\%} does for simple loops: <>= # doRNG must not be registered registerDoParallel(cl) # generate sequence of seeds of length the number of computations n <- 10; p <- 5 rng <- RNGseq( n * p, 1234) # run standard nested foreach loop res <- foreach(i=1:n) %:% foreach(j=1:p, r=rng[(i-1)*p + 1:p]) %dopar% { # set RNG seed rngtools::setRNG(r) # do your own computation ... c(i, j, rnorm(1)) } # Compare against the equivalent sequential computations k <- 1 res2 <- foreach(i=1:n) %:% foreach(j=1:p) %do%{ # set seed rngtools::setRNG(rng[[k]]) k <- k + 1 # do your own computation ... c(i, j, rnorm(1)) } stopifnot( identical(res, res2) ) @ The following is a more complex example with unequal -- but \textbf{known \emph{a priori}} -- numbers of iterations performed in the inner loops: <>= # generate sequence of seeds of length the number of computations n <- 10 rng <- RNGseq( n * (n+1) / 2, 1234) # run standard nested foreach loop res <- foreach(i=1:n) %:% foreach(j=1:i, r=rng[(i-1)*i/2 + 1:i]) %dopar%{ # set RNG seed rngtools::setRNG(r) # do your own computation ... c(i, j, rnorm(1)) } # Compare against the equivalent sequential computations k <- 1 res2 <- foreach(i=1:n) %:% foreach(j=1:i) %do%{ # set seed rngtools::setRNG(rng[[k]]) k <- k + 1 # do your own computation ... c(i, j, rnorm(1)) } stopifnot( identical(res, res2) ) @ \subsection{Conditional loops} The work around used for nested loops applies to conditional loops that use the \code{when()} clause. It ensures that the RNG seed use for a given inner iteration does not depend on the filter, but only on its index in the unconditional-unfolded loop: <>= # un-conditional single loop resAll <- foreach(i=1:n, .options.RNG=1234) %dorng%{ # do your own computation ... c(i, rnorm(1)) } # generate sequence of RNG rng <- RNGseq(n, 1234) # conditional loop: even iterations resEven <- foreach(i=1:n, r=rng) %:% when(i %% 2 == 0) %dopar%{ # set RNG seed rngtools::setRNG(r) # do your own computation ... c(i, rnorm(1)) } # conditional loop: odd iterations resOdd <- foreach(i=1:n, r=rng) %:% when(i %% 2 == 1) %dopar%{ # set RNG seed rngtools::setRNG(r) # do your own computation ... c(i, rnorm(1)) } # conditional loop: only first 2 and last 2 resFL <- foreach(i=1:n, r=rng) %:% when(i %in% c(1,2,n-1,n)) %dopar%{ # set RNG seed rngtools::setRNG(r) # do your own computation ... c(i, rnorm(1)) } # compare results stopifnot( identical(resAll[seq(2,n,by=2)], resEven) ) stopifnot( identical(resAll[seq(1,n,by=2)], resOdd) ) stopifnot( identical(resAll[c(1,2,n-1,n)], resFL) ) @ \subsection{Nested conditional loops} Conditional nested loops may use the same work around, as shown in this intricate example: <>= # generate sequence of seeds of length the number of computations n <- 10 rng <- RNGseq( n * (n+1) / 2, 1234) # run standard nested foreach loop res <- foreach(i=1:n) %:% when(i %% 2 == 0) %:% foreach(j=1:i, r=rng[(i-1)*i/2 + 1:i]) %dopar%{ # set RNG seed rngtools::setRNG(r) # do your own computation ... c(i, j, rnorm(1)) } # Compare against the equivalent sequential computations k <- 1 resAll <- foreach(i=1:n) %:% foreach(j=1:i) %do%{ # set seed rngtools::setRNG(rng[[k]]) k <- k + 1 # do your own computation ... c(i, j, rnorm(1)) } stopifnot( identical(resAll[seq(2,n,by=2)], res) ) @ \section{Performance overhead} The extra setup performed by the \code{\%dorng\%} operator leads to a slight performance over-head, which might be significant for very quick computations, but should not be a problem for realistic computations. The benchmarks below show that a \code{\%dorng\%} loop may take up to two seconds more than the equivalent \code{\%dopar\%} loop, which is not significant in practice, where parallelised computations typically take several minutes. <>= # load rbenchmark library(rbenchmark) # comparison is done on sequential computations registerDoSEQ() rPar <- function(n, s=0){ foreach(i=1:n) %dopar% { Sys.sleep(s) } } rRNG <- function(n, s=0){ foreach(i=1:n) %dorng% { Sys.sleep(s) } } # run benchmark cmp <- benchmark(rPar(10), rRNG(10) , rPar(25), rRNG(25) , rPar(50), rRNG(50) , rPar(50, .01), rRNG(50, .01) , rPar(10, .05), rRNG(10, .05) , replications=5) # order by increasing elapsed time cmp[order(cmp$elapsed), ] @ \section{Known issues} \label{sec:issues} \begin{itemize} \item Nested and/or conditional foreach loops using the operator \code{\%:\%} are not currently not supported (see \cref{sec:nested} for a work around). \item An error is thrown in \code{doRNG} 1.2.6, when the package \code{iterators} was not loaded, when used with \code{foreach} >= 1.4. \item There was a bug in versions prior to \code{1.4}, which caused \code{set.seed} and \code{.options.RNG} not to be equivalent when the current RNG was \code{"L'Ecuyer-CMRG"}. This behaviour can still be reproduced by setting: <>= doRNGversion('1.3') @ To revert to the latest default behaviour: <>= doRNGversion(NULL) @ \end{itemize} \section{News and changes} {\scriptsize \begin{verbatim} <>= cat(paste(readLines(system.file('NEWS', package='doRNG')), collapse="\n")) @ \end{verbatim} } \section*{Cleanup} <>= stopCluster(cl) @ \section*{Session information} \addcontentsline{toc}{section}{Session information} <>= sessionInfo() @ \printbibliography[heading=bibintoc] \end{document} doRNG/NEWS0000644000176200001440000001276213612460574011742 0ustar liggesusers************************************************************************* Changes in version 1.8 ************************************************************************* CHANGES o Unit tests are now run through testthat o Minor fixes in man pages and README file o Now depends on rngtools >= 1.3 o The result list gains an attribute 'doRNG_version' that contains the version of doRNG that was used, based on doRNGversion(). NB: this is not necessarily the same as the version of the installed package. o Added the following global option 'doRNG.rng_change_warning_skip'. See ?`%dorng%` (issue #14). o Moved dependency on pkgmaker to Suggests to make installation lighter (issue #10). FIXES o Enabled running %dorng% loops within a package (incorporating the solution proposed by Elizabeth Byerly in PR#3) o Fixed error with NULL iteration results when setting 'rng' attribute (issue #9) o Fixed error when using unamed foreach arguments (issue #8) o Fixed non-reproducibility issue when the .Random.seed is not yet initialized, e.g., when the session starts and the RNG has not been used yet (issue #12) o Fixed runtime error when package is not attached (issue #13) ************************************************************************* Changes in version 1.6.2 ************************************************************************* FIXES o Non reproducible %dorng% loop when doRNG is registered over doSEQ (Issue #1 reported by Brenton Kenkel). Actually due to %dorng% not restoring the RNG (to state + 1) when doRNG is registered over doSEQ. o %dorng% was not working properly on loops of length one (Issue #2) ************************************************************************* Changes in version 1.6 ************************************************************************* CHANGES o doRNG now depends on the package pkgmaker (>= 0.20) FIXES o Check error due number of cores used. Now limited to 2 in examples, vignette and unit test. ************************************************************************* Changes in version 1.5 ************************************************************************* CHANGES o doRNG now depends on the package pkgmaker (>= 0.9) o improved vignette o most of the general RNG utilities have been incorporated in a new package called rngtools. ************************************************************************* Changes in version 1.4.1 ************************************************************************* CHANGES o when the current RNG was L'Ecuyer-CMRG, unseeded loops now use the current RNG stream as for the first stream in the RNG sequence and changes the current RNG to the next RNG stream of the last stream in the sequence. BUG FIX o fix error "'iter' not found" due to changes in foreach package dependencies -- that was announced by Rich Calaway. o loops seeded with set.seed and .options.RNG were not reproducible when current RNG was L'Ecuyer-CMRG (reported by Zhang Peng) o separate unseeded loops were sharing most of their streams, when current RNG was L'Ecuyer-CMRG the RNG seed. o nested/conditional loops were crashing with a bad error. They are still not supported but the error message is nicer and a work around has been added to the vignette (reported by Chanhee Yi and Zhang Peng). ************************************************************************* Changes in version 1.2.3 ************************************************************************* BUG FIX o fixed error when running a %dorng% loop on a fresh session, with no parallel backend registered. CHANGES o improved vignette o added more unit tests o changed the name of the RNG attribute on result of %dorng% looops from 'RNG' to 'rng'. It now contains the whole sequence of RNG seeds, instead of only the first one. o RNGseq now accepts a list or a matrix describing the whole sequence of seeds. See vignette for more details. o %dorng% loops can be seeded with a complete sequence of seeds passed as a list, a matrix, or an object with attribute 'rng', e.g. the results of %dorng% loops. See vignette for more details. ************************************************************************* Changes in version 1.2.2 ************************************************************************* BUG FIX o separate %dorng% loops were using the same seed. NEW FEATURES o add unit tests o first seed is set as an attribute of the loop's result CHANGES o function doRNGseed now returns the seed to use for the first iteration. o RNGseq now change the current RNG state if called with no seed specific. DEFUNCT o removed function CMRGseed ************************************************************************* Changes in version 1.2 ************************************************************************* BUG FIX o An error was thrown if using %dorng% loops before using any random generator. Thanks to Eric Lehmann for reporting this. CHANGES o add vignette o use package doParallel in examples ************************************************************************* Changes in version 1.1 ************************************************************************* CHANGES o use R core RNG "L'Ecuyer-CMRG" and the parallel package, instead of the implementation provided by the rstream package. doRNG/R/0000755000176200001440000000000013612460574011434 5ustar liggesusersdoRNG/R/utils.R0000644000176200001440000000054513612460574012723 0ustar liggesusers # from pkgmaker 0.31 ns_get <- function (x, ns = NULL, ...){ if (is.null(ns)) { ns <- gsub("^([^:]+)::.*", "\\1", x) x <- gsub(".*::([^:]+)$", "\\1", x) } if (!isNamespace(ns)) { ns <- tryCatch(asNamespace(ns), error = function(e) NULL) if (is.null(ns)) return() } get0(x, envir = ns, ...) }doRNG/R/doRNG-package.R0000644000176200001440000000477613612460574014137 0ustar liggesusers#' The \emph{doRNG} package provides functions to perform #' reproducible parallel foreach loops, using independent random streams #' as generated by L'Ecuyer's combined multiple-recursive generator [L'Ecuyer (1999)]. #' It enables to easily convert standard %dopar% loops into fully reproducible loops, #' independently of the number of workers, the task scheduling strategy, #' or the chosen parallel environment and associated foreach backend. #' It has been tested with the following foreach backend: doMC, doSNOW, doMPI. #' #' @encoding UTF-8 #' @name doRNG-package #' @docType package #' @title Generic Reproducible Parallel Backend for foreach Loops #' @keywords package #' @seealso \code{\link{doRNG}}, \code{\link{RNGseq}} #' @bibliography /home/renaud/Documents/articles/library.bib #' @cite Lecuyer1999 #' #' @import stats rngtools foreach #' @examples #' #' # register parallel backend #' library(doParallel) #' cl <- makeCluster(2) #' registerDoParallel(cl) #' #' ## standard %dopar% loop are not reproducible #' set.seed(123) #' r1 <- foreach(i=1:4) %dopar%{ runif(1) } #' set.seed(123) #' r2 <- foreach(i=1:4) %dopar%{ runif(1) } #' identical(r1, r2) #' \dontshow{ stopifnot(!identical(r1, r2)) } #' #' ## %dorng% loops _are_ reproducible #' set.seed(123) #' r1 <- foreach(i=1:4) %dorng%{ runif(1) } #' set.seed(123) #' r2 <- foreach(i=1:4) %dorng%{ runif(1) } #' identical(r1, r2) #' \dontshow{ stopifnot(identical(r1, r2)) } #' #' # alternative way of seeding #' a1 <- foreach(i=1:4, .options.RNG=123) %dorng%{ runif(1) } #' a2 <- foreach(i=1:4, .options.RNG=123) %dorng%{ runif(1) } #' identical(a1, a2) && identical(a1, r1) #' \dontshow{ stopifnot(identical(a1, a2) && identical(a1, r1)) } #' #' ## sequences of %dorng% loops _are_ reproducible #' set.seed(123) #' s1 <- foreach(i=1:4) %dorng%{ runif(1) } #' s2 <- foreach(i=1:4) %dorng%{ runif(1) } #' identical(s1, r1) && !identical(s1, s2) #' \dontshow{ stopifnot(identical(s1, r1) && !identical(s1, s2)) } #' #' set.seed(123) #' s1.2 <- foreach(i=1:4) %dorng%{ runif(1) } #' s2.2 <- foreach(i=1:4) %dorng%{ runif(1) } #' identical(s1, s1.2) && identical(s2, s2.2) #' \dontshow{ stopifnot(identical(s1, s1.2) && identical(s2, s2.2)) } #' #' ## Non-invasive way of converting %dopar% loops into reproducible loops #' registerDoRNG(123) #' s3 <- foreach(i=1:4) %dopar%{ runif(1) } #' s4 <- foreach(i=1:4) %dopar%{ runif(1) } #' identical(s3, s1) && identical(s4, s2) #' \dontshow{ stopifnot(identical(s3, s1) && identical(s4, s2)) } #' #' stopCluster(cl) #' "_PACKAGE" doRNG/R/doRNG.R0000644000176200001440000004623313612460574012540 0ustar liggesusers# Development of a dorng equivalent to dopar for reproducible loops # # Author: Renaud Gaujoux # Creation: 17 Aug 2011 ############################################################################### #library(foreach) # or-NULL operator (borrowed from Hadley Wickham) '%||%' <- function(x, y) if( !is.null(x) ) x else y #' @importFrom utils head .collapse <- function(x, n=length(x), sep=', '){ res <- paste(if( missing(n) ) x else head(x, n), collapse=', ') if( length(x) > n ) res <- paste(res, '...', sep=', ') res } #' Back Compatibility Option for doRNG #' #' Sets the behaviour of \%dorng\% foreach loops from a #' given version number. #' #' @section Behaviour changes in versions: #' #' \describe{ #' \item{1.4}{ The behaviour of \code{doRNGseed}, and therefore of #' \code{\%dorng\%} loops, changed in the case where the current RNG was #' L'Ecuyer-CMRG. #' Using \code{set.seed} before a non-seeded loop used not to be identical #' to seeding via \code{.options.RNG}. #' Another bug was that non-seeded loops would share most of their RNG seed! #' } #' \item{1.7.4}{Prior to this version, in the case where the RNG had not been called yet, #' the first seeded \code{\%dorng\%} loops would not give the identical results as #' subsequent loops despite using the same seed #' (see \url{https://github.com/renozao/doRNG/issues/12}). #' #' This has been fixed in version 1.7.4, where the RNG is called once (\code{sample(NA)}), #' whenever the .Random.seed is not found in global environment. #' } #' } #' #' @param x version number to switch to, or missing to get the currently #' active version number, or \code{NULL} to reset to the default behaviour, #' i.e. of the latest version. #' #' @return a character string #' If \code{x} is missing this function returns the version number from the #' current behaviour. #' If \code{x} is specified, the function returns the old value of the #' version number (invisible). #' #' @importFrom utils packageVersion #' @export #' @examples #' #' \dontshow{ registerDoSEQ() } #' #' ## Seeding when current RNG is L'Ecuyer-CMRG #' RNGkind("L'Ecuyer") #' #' doRNGversion("1.4") #' # in version >= 1.4 seeding behaviour changed to fix a bug #' set.seed(123) #' res <- foreach(i=1:3) %dorng% runif(1) #' res2 <- foreach(i=1:3) %dorng% runif(1) #' stopifnot( !identical(attr(res, 'rng')[2:3], attr(res2, 'rng')[1:2]) ) #' res3 <- foreach(i=1:3, .options.RNG=123) %dorng% runif(1) #' stopifnot( identical(res, res3) ) #' #' # buggy behaviour in version < 1.4 #' doRNGversion("1.3") #' res <- foreach(i=1:3) %dorng% runif(1) #' res2 <- foreach(i=1:3) %dorng% runif(1) #' stopifnot( identical(attr(res, 'rng')[2:3], attr(res2, 'rng')[1:2]) ) #' res3 <- foreach(i=1:3, .options.RNG=123) %dorng% runif(1) #' stopifnot( !identical(res, res3) ) #' #' # restore default RNG #' RNGkind("default") #' # restore to current doRNG version #' doRNGversion(NULL) #' doRNGversion <- local({ currentV <- "1.7.4" #as.character(packageVersion('doRNG')) cache <- currentV function(x){ if( missing(x) ) return(cache) if( is.null(x) ) x <- currentV # update cache and return old value old <- cache cache <<- x invisible(old) } }) #' @importFrom utils compareVersion checkRNGversion <- function(x){ compareVersion(doRNGversion(), x) } doRNGseq <- function(n, seed=NULL, ...){ # compute sequence using rngtools::RNGseq # library(rngtools) res <- RNGseq(n, seed, ..., version=if( checkRNGversion('1.4') >=0 ) 2 else 1, simplify = FALSE) } #' Getting Information About doRNG Foreach Backend #' #' \code{infoDoRNG} returns information about the doRNG backend, e.g., version, #' number of workers. #' It is not meant to be called by the user. #' #' #' @param data a list of data used by the backend #' @param item the data item requested, as a character string #' (e.g. 'name', 'workers', 'version') #' #' @return \code{infoDoRNG} returns the requested info (usually as a character #' string or a numeric value). #' #' @keywords internal #' @author Renaud Gaujoux #' infoDoRNG <- function (data, item) { switch(item , workers = data$backend$info(data$backend$data, "workers") , name = "doRNG" , version = "doRNG 1.7.3" , NULL) } #' @describeIn infoDoRNG implements the generic reproducible foreach backend. It should #' not be called directly by the user. #' #' @param obj a foreach description of the loop arguments #' @param ex the lopp expression #' @param envir the loop's evaluation environment #' @param data configuration data of the doRNG backend #' doRNG <- function (obj, ex, envir, data){ if( is.null(obj$options) ) obj$options <- list() if( !'RNG' %in% names(obj$options) ){ obj$options$RNG <- if( !data$once || data$nseed==0 ){ #message("doRNG backend - use seed ", if( data$once ) "only once" else "for every loop", ":") data$seed } else NULL } # data$nseed <- data$nseed + 1 # assign('data', data, pos=foreach:::.foreachGlobals) rngBackend <- getDoBackend() # increment number of calls to doRNG rngBackend$data$nseed <- rngBackend$data$nseed + 1 # directly register (temporarly) the computing backend on.exit({setDoBackend(rngBackend)}, add=TRUE) setDoBackend(rngBackend$data$backend) do.call(doRNG::`%dorng%`, list(obj, ex), envir = envir) } ##% Get/Sets the registered foreach backend's data getDoBackend <- function(){ # one has to get the complete set of backend data from within the foreach Namespace foreach_ns <- asNamespace('foreach') # .foreachGlobals <- get('.foreachGlobals', foreach_ns) .foreachGlobals <- ns_get('.foreachGlobals', foreach_ns) # getDoPar <- get('getDoPar', foreach_ns) getDoPar <- ns_get('getDoPar', foreach_ns) c(getDoPar() , info= if( exists("info", where = .foreachGlobals, inherits = FALSE) ) .foreachGlobals$info else function(data, item) NULL) } setDoBackend <- function(backend){ ob <- getDoBackend() do.call('setDoPar', backend) invisible(ob) } .getDoParName <- function(backend = getDoBackend(), version = FALSE) { if ( !is.null(backend[['info']]) ){ res <- backend[['info']](backend[['data']], "name") if( version ) paste0(res, '(', backend[['info']](backend[['data']], "version"), ')') res } } #' Reproducible Parallel Foreach Backend #' #' \code{\%dorng\%} is a foreach operator that provides an alternative operator #' \code{\%dopar\%}, which enable reproducible foreach loops to be performed. #' #' @param obj a foreach object as returned by a call to \code{\link{foreach}}. #' @param ex the \code{R} expression to evaluate. #' #' @return \code{\%dorng\%} returns the result of the foreach loop. See \code{\link{\%dopar\%}}. #' The whole sequence of RNG seeds is stored in the result object as an attribute. #' Use \code{attr(res, 'rng')} to retrieve it. #' #' @section Global options: #' #' These options are for advanced users that develop `foreach backends: #' #' * 'doRNG.rng_change_warning_skip': if set to a single logical `FALSE/TRUE`, it indicates #' whether a warning should be thrown if the RNG seed is changed by the registered #' parallel backend (default=FALSE). #' Set it to `TRUE` if you know that running your backend will change the RNG state and #' want to disable the warning. #' This option can also be set to a character vector that specifies the name(s) of the backend(s) #' for which the warning should be skipped. #' #' @importFrom iterators iter #' @export #' @usage obj \%dorng\% ex #' @seealso \code{\link{foreach}}, \code{\link[doParallel]{doParallel}} #' , \code{\link[doParallel]{registerDoParallel}}, \code{\link[doMPI]{doMPI}} #' @examples #' #' library(doParallel) #' cl <- makeCluster(2) #' registerDoParallel(cl) #' #' # standard %dopar% loops are _not_ reproducible #' set.seed(1234) #' s1 <- foreach(i=1:4) %dopar% { runif(1) } #' set.seed(1234) #' s2 <- foreach(i=1:4) %dopar% { runif(1) } #' identical(s1, s2) #' #' # single %dorng% loops are reproducible #' r1 <- foreach(i=1:4, .options.RNG=1234) %dorng% { runif(1) } #' r2 <- foreach(i=1:4, .options.RNG=1234) %dorng% { runif(1) } #' identical(r1, r2) #' # the sequence os RNG seed is stored as an attribute #' attr(r1, 'rng') #' #' # stop cluster #' stopCluster(cl) #' #' # More examples can be found in demo `doRNG` #' \dontrun{ #' demo('doRNG') #' } #' #' @demo Some features of the %dorng% foreach operator #' #' library(doRNG) #' library(doParallel) #' #' if( .Platform$OS.type == "unix" ){ #' registerDoParallel(2) #' #' # single %dorng% loops are reproducible #' r1 <- foreach(i=1:4, .options.RNG=1234) %dorng% { runif(1) } #' r2 <- foreach(i=1:4, .options.RNG=1234) %dorng% { runif(1) } #' identical(r1, r2) #' # the sequence os RNG seed is stored as an attribute #' attr(r1, 'rng') #' #' # sequences of %dorng% loops are reproducible #' set.seed(1234) #' s1 <- foreach(i=1:4) %dorng% { runif(1) } #' s2 <- foreach(i=1:4) %dorng% { runif(1) } #' # two consecutive (unseed) %dorng% loops are not identical #' identical(s1, s2) #' #' # But the whole sequence of loops is reproducible #' set.seed(1234) #' s1.2 <- foreach(i=1:4) %dorng% { runif(1) } #' s2.2 <- foreach(i=1:4) %dorng% { runif(1) } #' identical(s1, s1.2) && identical(s2, s2.2) #' # it gives the same result as with .options.RNG #' identical(r1, s1) #' #' } #' #' # Works with SNOW-like and MPI clusters #' # SNOW-like cluster #' cl <- makeCluster(2) #' registerDoParallel(cl) #' #' s1 <- foreach(i=1:4, .options.RNG=1234) %dorng% { runif(1) } #' s2 <- foreach(i=1:4, .options.RNG=1234) %dorng% { runif(1) } #' identical(s1, s2) #' #' stopCluster(cl) #' registerDoSEQ() #' #' # MPI cluster #' library(doMPI) #' cl <- startMPIcluster(2) #' registerDoMPI(cl) #' #' s1 <- foreach(i=1:4, .options.RNG=1234) %dorng% { runif(1) } #' s2 <- foreach(i=1:4, .options.RNG=1234) %dorng% { runif(1) } #' identical(s1, s2) #' #' closeCluster(cl) #' registerDoSEQ() #' #' `%dorng%` <- function(obj, ex){ #library(rngtools) # str(obj) # dump verbose messages if not in verbose mode verbose <- !is.null(obj$verbose) && obj$verbose if( !verbose ) message <- function(...) NULL # exit if nested or conditional loop if( any(c('xforeach', 'filteredforeach') %in% class(obj)) ) stop("nested/conditional foreach loops are not supported yet.\nSee the package's vignette for a work around.") # if an RNG seed is provided then setup random streams # and add the list of RNGs to use as an iterated arguments for %dopar% # library(parallel) N_elem <- length(as.list(iter(obj))) obj$argnames <- c(obj$argnames, '.doRNG.stream') obj$args$.doRNG.stream <- rep(NA_integer_, N_elem) # make sure the RNG seed is initialized by calling getRNG() if( is.null(RNGseed()) ){ if( checkRNGversion("1.7.4") >= 0 ){ message("NOTE -- .Random.seed is not initialized: sampling once to ensure reproducibility.") getRNG() }else{ warning(paste0(".Random.seed is not initialized: results might not be reproducible.\n ", "Update to doRNG version >= 1.7.4 to get a fix for this issue.")) } } ## # restore current RNG on exit if a seed is passed rngSeed <- if( !is.null(obj$options$RNG) ){ # setup current RNG restoration RNG.old <- RNGseed() on.exit({RNGseed(RNG.old)}, add=TRUE) # extract RNG setting from object if possible (do not resolve single seed) rngSeed <- getRNG(obj$options$RNG, num.ok=TRUE) %||% obj$options$RNG # ensure it is a list # NB: unnamed lists are sequences of seeds if( !is.list(rngSeed) || is.null(names(rngSeed)) ){ rngSeed <- list(rngSeed) } rngSeed } # message("* Seed specification: ", str_out(rngSeed, 6, total = length(rngSeed) > 6)) # generate a sequence of streams # print("before RNGseq") # showRNG() obj$args$.doRNG.stream <- do.call("doRNGseq", c(list(n=N_elem, verbose=obj$verbose), rngSeed)) # print("after RNGseq") # showRNG() #print(obj$args$.doRNG.stream) message("* Registered backend: ", .getDoParName(version = TRUE)) dp <- getDoParName() # directly register (temporarly) the computing backend if( !is.null(dp) && dp == 'doRNG' ){ rngBackend <- getDoBackend() message("* Registering computing backend: ", .getDoParName(rngBackend$data$backend, version = TRUE)) on.exit({ message("* Restoring previous backend: ", .getDoParName(rngBackend)) setDoBackend(rngBackend) }, add=TRUE) setDoBackend(rngBackend$data$backend) dp <- getDoParName() } ## SEPCIAL CASE FOR doSEQ or doMPI # TODO: figure out why doMPI draws once from the current RNG (must be linked # to using own code to setup L'Ecuyer RNG) # restore RNG settings as after RNGseq if doSEQ is the backend and no seed was passed if( is.null(obj$options$RNG) ){ RNG.old <- RNGseed() on.exit({ rng_type_changed <- !identical(RNGtype(), RNGtype(RNG.old)) warning_skip <- getOption("doRNG.rng_change_warning_skip", FALSE) force_warning <- getOption("doRNG.rng_change_warning_force", FALSE) known_changing_cases <- is.null(dp) || dp %in% c("doSEQ", "doMPI") || (is.logical(warning_skip) && !is.na(warning_skip) && warning_skip) || (is.character(warning_skip) && dp %in% warning_skip) if( known_changing_cases || rng_type_changed ){ if( force_warning || (rng_type_changed && !known_changing_cases) ){ warning(sprintf("Foreach loop (%s) had changed the current RNG type: RNG was restored to same type, next state", dp %||% "unknown")) }else{ message("* Detected known RNG side effect: ", dp) } message("* Restoring RNG as after RNG sequence generation") if( verbose ) showRNG(RNG.old, indent = " -") RNGseed(RNG.old) message("OK") } }, add=TRUE) } ## # export package doRNG if not already exported if( !('doRNG' %in% obj$packages) ) obj$packages <- c(obj$packages, 'doRNG') # append code to the loop expression to set the RNG ex <- as.call(list(as.name('{'), quote({rngtools::RNGseed(.doRNG.stream);}), substitute(ex))) # call the standard %dopar% operator res <- do.call('%dopar%', list(obj, ex), envir=parent.frame()) # add seed sequence as an attribute (skip this for NULL results) if( !is.null(res) ){ attr(res, 'rng') <- obj$args$.doRNG.stream attr(res, 'doRNG_version') <- doRNGversion() } # return result res } #' Registering doRNG for Persistent Reproducible Parallel Foreach Loops #' #' \code{registerDoRNG} registers the doRNG foreach backend. #' Subsequent \%dopar\% loops are then performed using the previously #' registered foreach backend, but are internally performed as \code{\link{\%dorng\%}} loops, #' making them fully reproducible. #' #' Briefly, the RNG is set, before each iteration, with seeds for L'Ecuyer's CMRG #' that overall generate a reproducible sequence of statistically independent #' random streams. #' #' Note that (re-)registering a foreach backend other than doRNG, after a call #' to \code{registerDoRNG} disables doRNG -- which then needs to be registered. #' #' @param seed a numerical seed to use (as a single or 6-length numerical value) #' @param once a logical to indicate if the RNG sequence should be seeded at the #' beginning of each loop or only at the first loop. #' #' @seealso \code{\link{\%dorng\%}} #' @export #' @examples #' #' library(doParallel) #' cl <- makeCluster(2) #' registerDoParallel(cl) #' #' # One can make reproducible loops using the %dorng% operator #' r1 <- foreach(i=1:4, .options.RNG=1234) %dorng% { runif(1) } #' # or convert %dopar% loops using registerDoRNG #' registerDoRNG(1234) #' r2 <- foreach(i=1:4) %dopar% { runif(1) } #' identical(r1, r2) #' stopCluster(cl) #' #' # Registering another foreach backend disables doRNG #' cl <- makeCluster(2) #' registerDoParallel(cl) #' set.seed(1234) #' s1 <- foreach(i=1:4) %dopar% { runif(1) } #' set.seed(1234) #' s2 <- foreach(i=1:4) %dopar% { runif(1) } #' identical(s1, s2) #' \dontshow{ stopifnot(!identical(s1, s2)) } #' #' # doRNG is re-nabled by re-registering it #' registerDoRNG() #' set.seed(1234) #' r3 <- foreach(i=1:4) %dopar% { runif(1) } #' identical(r2, r3) #' # NB: the results are identical independently of the task scheduling #' # (r2 used 2 nodes, while r3 used 3 nodes) #' #' # argument `once=FALSE` reseeds doRNG's seed at the beginning of each loop #' registerDoRNG(1234, once=FALSE) #' r1 <- foreach(i=1:4) %dopar% { runif(1) } #' r2 <- foreach(i=1:4) %dopar% { runif(1) } #' identical(r1, r2) #' #' # Once doRNG is registered the seed can also be passed as an option to %dopar% #' r1.2 <- foreach(i=1:4, .options.RNG=456) %dopar% { runif(1) } #' r2.2 <- foreach(i=1:4, .options.RNG=456) %dopar% { runif(1) } #' identical(r1.2, r2.2) && !identical(r1.2, r1) #' \dontshow{ stopifnot(identical(r1.2, r2.2) && !identical(r1.2, r1)) } #' #' stopCluster(cl) #' registerDoRNG <- function(seed=NULL, once=TRUE){ backend <- getDoBackend() # use stored backend if registerDoRNG was called repeatedly if( identical(getDoParName(), 'doRNG') ) backend <- backend$data$backend # set the current RNG with seed immediately if only used once if( once && !is.null(seed) ){ if( !is.numeric(seed) || length(seed)!=1L ) stop("Invalid seed: must be a single numeric value.") set.seed(seed) seed <- NULL } setDoPar(doRNG, list(seed=seed, once=once, nseed=0, backend=backend), infoDoRNG) } ###% Reproducibly Apply a Function over a List or Vector ###% ###% @aliases xapply reproduce ###% ###% \code{reproduce} and \code{xapply} are a reproducible versions ###% of \code{\link{replicate}} and \code{\link{sapply}} respectively, ###% that ensures the reproducibility of the results, when stochastic computations ###% are involved. ###% ###% The reproducibility is achieved by using LEcuyer's RNG provided by R core ###% since R-2.14.0, to generate independent random streams ###% that are used as the random number generator for each replicate. ###% ###% @param n the number of replication as a single numeric (integer) ###% @param seed the main numerical seed used to initialize the sequence of random ###% streams ###% @param expr the expression (language object, usually a call) to evaluate repeatedly ###% @param simplify logical; should the result be simplified to a vector or ###% matrix if possible? ###% ###% ###% #reproduce <- function (n, expr, seed=NULL, simplify = TRUE){ # f <- eval.parent(substitute(function(...) expr)) # xapply(integer(n), seed, f, simplify = simplify) #} # #xapply <- function (X, FUN, seed=NULL, ..., simplify = TRUE, USE.NAMES = TRUE){ # # # generate a sequence of streams # .RNG.stream <- RNGseq(length(X), seed, packed=TRUE) # # # keep current RNG and restore it on exit (useful for the sequential backend doSEQ) # RNG.old <- rstream.RNG() # on.exit(rstream.RNG(RNG.old), add=TRUE) # # # append code to the loop expression to set the RNG # expr <- as.call(list(as.name('{'), # quote({doRNGseed(.rng);}), # quote(do.call(FUN, list(...))))) # # env <- environment(FUN) # f <- eval(substitute(function(.rng, ..., FUN) expr), env) # mapply(f, .RNG.stream, X, MoreArgs=c(list(...), FUN=FUN), # SIMPLIFY = simplify, USE.NAMES= USE.NAMES) #} doRNG/MD50000644000176200001440000000215613613501566011545 0ustar liggesusersd49bb0ae4a75d09a9aba4b8c92dafc2f *DESCRIPTION 914736c637844ee4cc539cb363543c7a *NAMESPACE 38ab5ac2b1fa1a76bf4f9b37708a6510 *NEWS a797aa4304fa09e42ded2f1d819a57c4 *R/doRNG-package.R 825b05f565a59bb39be5c5bc422e6313 *R/doRNG.R adaad203188938606a548fed7fb7982d *R/utils.R aa2abf2c0fdb22da15983f1863f43eb1 *build/vignette.rds 00e481a40fea9fb88bdd71c6e39fd332 *demo/00Index 3c7f2a369c28a79e7b45d8b4b0cda2d6 *demo/doRNG.R 20daaa122d0172ca9915c95d11765be1 *inst/REFERENCES.bib a64d2932a0800f4d39c4806c095876b2 *inst/doc/doRNG.R 01e38c562116701d37c64642b42cc41f *inst/doc/doRNG.Rnw 97e3986a19dd307a1f521070726fd285 *inst/doc/doRNG.pdf 4b8e75efe02ce7930431e5f77ac632d7 *man/doRNG-package.Rd 2ae08e7ec1251d8649f840809cbb6d7b *man/doRNGversion.Rd d1d1a9eba52728e46838c19a8ceb4675 *man/grapes-dorng-grapes.Rd b8ee154d2234e130c163337519902da4 *man/infoDoRNG.Rd 14107ba91378ad10aea3b7b22e9a4bf5 *man/registerDoRNG.Rd afa2c0e8da402461ed281edb4f4e20f7 *tests/testthat.R 7978c192923a6be825d7a6d4cb9f2cea *tests/testthat/test-doRepro.r 979bef80cc9c2ac61f77720925044b42 *tests/testthat/test-dorng.r 01e38c562116701d37c64642b42cc41f *vignettes/doRNG.Rnw doRNG/inst/0000755000176200001440000000000013556341614012210 5ustar liggesusersdoRNG/inst/REFERENCES.bib0000644000176200001440000000734013612122403014275 0ustar liggesusers@Article{Hothorn2011, abstract = {Reproducible research is a concept of providing access to data and software along with published scientific findings. By means of some case studies from different disciplines, we will illustrate reasons why readers should be given the possibility to look at the data and software independently from the authors of the original publication. We report results of a survey comprising 100 papers recently published in Bioinformatics. The main finding is that authors of this journal share a culture of making data available. However, the number of papers where source code for simulation studies or analyzes is available is still rather limited.}, author = {Torsten Hothorn and Friedrich Leisch}, doi = {10.1093/bib/bbq084}, file = {:home/renaud/Documents/articles/Reproducible research/Case studies in reproducibility{\_}Hothorn2011.pdf:pdf}, issn = {1477-4054}, journal = {Briefings in bioinformatics}, keywords = {reproducible research,software,statistical analyzes,sweave}, month = {jan}, pmid = {21278369}, title = {{Case studies in reproducibility.}}, url = {http://www.ncbi.nlm.nih.gov/pubmed/21278369}, year = {2011}, } @Misc{Stodden2011, author = {Victoria C Stodden}, booktitle = {AAAS Annual Meeting}, title = {{The Digitization of Science: Reproducibility and Interdisciplinary Knowledge Transfer}}, url = {http://aaas.confex.com/aaas/2011/webprogram/Session3166.html}, year = {2011}, } @Article{Ioannidis2008, abstract = {Given the complexity of microarray-based gene expression studies, guidelines encourage transparent design and public data availability. Several journals require public data deposition and several public databases exist. However, not all data are publicly available, and even when available, it is unknown whether the published results are reproducible by independent scientists. Here we evaluated the replication of data analyses in 18 articles on microarray-based gene expression profiling published in Nature Genetics in 20052006. One table or figure from each article was independently evaluated by two teams of analysts. We reproduced two analyses in principle and six partially or with some discrepancies; ten could not be reproduced. The main reason for failure to reproduce was data unavailability, and discrepancies were mostly due to incomplete data annotation or specification of data processing and analysis. Repeatability of published microarray studies is apparently limited. More strict publication rules enforcing public data availability and explicit description of data processing and analysis should be considered.}, author = {John P A Ioannidis and David B Allison and Catherine A Ball and Issa Coulibaly and Xiangqin Cui and Aed\'in C Culhane and Mario Falchi and Cesare Furlanello and Laurence Game and Giuseppe Jurman and Jon Mangion and Tapan Mehta and Michael Nitzberg and Grier P Page and Enrico Petretto and Vera {Van Noort}}, doi = {10.1038/ng.295}, issn = {10614036}, journal = {Nature Genetics}, number = {2}, pages = {149--155}, publisher = {Nature Publishing Group}, title = {{The reproducibility of lists of differentially expressed genes in microarray studies}}, url = {http://www.nature.com/doifinder/10.1038/ng.295}, volume = {41}, year = {2008}, } @Article{Lecuyer1999, author = {Pierre L'Ecuyer}, file = {:home/renaud/Documents/articles/stats/Good Parameters and Implementations for Combined Multiple Recursive Random Number Generators\_Lecuyer1999.pdf:pdf}, doi = {10.1287/opre.47.1.159}, journal = {Operations Research}, number = {1}, title = {{Good parameters and implementations for combined multiple recursive random number generators}}, url = {http://www.jstor.org/stable/10.2307/222902}, volume = {47}, year = {1999}, } doRNG/inst/doc/0000755000176200001440000000000013613333422012745 5ustar liggesusersdoRNG/inst/doc/doRNG.pdf0000644000176200001440000070506513613333422014426 0ustar liggesusers%PDF-1.5 % 88 0 obj << /Length 1952 /Filter /FlateDecode >> stream xڵXM6ϯ%UTU >]KN%݋Z%f$R!o7R $E@x4Y%4ysEO^SYEҜh)2y")O[|}6#2 es뛸l"]Z"(傫n!yZ6aXjnSjd\z*/p& ʗ^~y0gaԵ]aCxiɅA$%׮.%ߛgܛdqVcdX\6pm|Oiz?5aL x<@՜ C;Й4iWIx~s1bSFy{)oXZ=E 80pr<4$_{p,"N ց~3Kz{#BJ i7sJMP;͵Eߴg}& aTg3_WR>v)A.Fh=8K,A8>V}piﺉY{b~Rqas1)ISyƹ2pl}_ P-Hq yT)]%Ru>|tFOs=|Xt !"u9'!wTx:|s" ׻L]H0^i!mٸ xQjz,3ϦRȦ?sC0{bÌ7r~nw`fG\#J ]w֧.O|:#>=8Va&YiAG-`p Oͧ0^h 3_n} rS ޕAC ml.6Guʌ^7 $zn*6ic4|{==lQ :i㇉W** dR.)rV?K9~17G =ƥ:f~jmrNއ7kWeET;T E$τ#T f d*?A|zv.=&x]ԫ,l¬ X 1|Q7=Vl FdRl?%64R 7bh;WK8RmHp s\/@A0̲tm 06ud6cՌ^Fqg3`Xk8 6 G0|;'>0~zp vy^=MQUYu9ys5eқf4[lt ZǾj㫭7}p,h+ҵƻ>Q L + !CA_m\U@\|Jl&ZWAea Gs'! *tBٚج.J^33}uqنe*Mn飜rXE0P+ہ>WZEfY2^yWt,,\EӮmѩT6n MB.0]2< Mq(7i3v)=&'a: ۺI_/k hRcJRj*(Z>5j pP9jlwaj=@Z*=X}q/uum~hqlqfrPg=wYxr Fl?@ a@ GLlAA &C?3J+/ >av@pׇo6JcemE1h/A Ē蚛>t#B%Pm0wz&%̿]$~:^|In.uh<Gm auϹ`T]PDhD/u_ZHa#~`'Mz~;?ǠPk'H>a endstream endobj 119 0 obj << /Length 2546 /Filter /FlateDecode >> stream x[oFֻ˸~5E{AqM xHwKU_D >f3;3;-E`BϓG}=N]<7JQ7?IOyQ*R^Hb-'n"#84B0N~y!#`F01%N'σK yW%V1H#Ηޅ<ԡ_TْKY Λ\duVeUhۢUm֛myU6W?=v0q9mJ`1(R" C/~0i@ .C5ϊP?pE/AeN 8¼6;MvmfsbK|gY[SzWqI>Jy,4D%,~/g6{:(䫎` 2DI53m5P=u7?{xsZzͺ55WB~Ysp1/'!%Ekqp9hPfI#o dwKw_gi: =fY.CP& 2#"V1cxz[W_C>@eO%_f?, p: Y^t/+.8biP' DkFq&QFQrZz|h,B0N},>fRt*}_f:WPKAkĮ7y]k.ܑ!?Ph$ǾKxc|kMamVkxW >}ȳb`u x&n vo++>mM$Xj!V`.F3f 2* &( n4F 6E~\hl0徰mSSS5|SWT^ئ ]*,/|j!`A=%-d%vLN@f ^U>_DУ~")Bx(BP)D*BT= -)xS)Fxc'x^-~Wg\b~{K)lrsuQUdq[ǩyy ȭ˲B|ix,&aPrrحAKC7v NK@C XV/큌.4Gm|ͫ.pR]sDTdObw%cDʛĝ&̢wvsvϥJ\қ+F E0Eu;2O-1nF?Q3 =&ξuo.. a e>|,TbϜ&-&";lj`nۄF!jl wĶx&.4Nf3gp:~bcr6>coVtlWЅu*eU5 q3YxeԘ+liw~1 }wvƟ[pld|įj 88Ұ&BkT2-7Gnjd#1֞xJzKh"Ļ%@)ީ/~|%0QSabvza bnr^9;=]!9i?vъ>u}6}N-F˄3zpa endstream endobj 129 0 obj << /Length 2544 /Filter /FlateDecode >> stream x]o8=BC2P}Cw{ݢ`X#l͐,)rdto H; H3IԎD Jr$8"O,(YY 2^7]Δ _HaeLn,Λ ; ipKIPEᝥ -'L0YXgkفV eOq"t (o) \H%a5N(k7XeEV 7Al@^xwbׇk={KilË|dpm#g8ZUx6'#FȡͭK `y!&fOqP7H$ jRo;hq#]RRMRDcY18Jҩ_mñtqꠂ`Z$1{w>=} tlMU2`quRKp.Q&bJˣ_(>n P0ٸjO|)L.IuR|ԺD]Ƒa8W``~(?m i'VSUR< w{a'\*j{e0\pk43$>R%ED+7ۼ!!8¦,ҲˆJ;?nӺJ זG఼SYg ,} |t jbh]xx2aɧg(:5Kſ\a5MYk?Ѣ#?4?Vh:>4j{ 15ܥ˧'r}ZU"_bɓE$?zvRHb %9Cx3 As7LsHb"(EӬhE~ B{Rn{/dٙM2`X##"e[!m%V¼qk\+ NE{:E 7"_l)(,c 鮤7XPK|uq\ܧ ` Ufn-ƭ k-ږ3g, F8:#i܊e\kP3W8ÊӶH:͊_r>H˫vGnzƱ 83y{MC8>1W|];/6(J.c(hi|'Q$dR9lځ4p5uk^@wO,n/oO\D 4;ocjꭹhQ; ` ٰ뢼`rX4[u;Cm4 Smj&p "QfX@Dmq%yfKȵfu~Dս| 7{;S~w;3 d75꿽.>ψPϰ X`Z9eg`}qxٙ9,qVyQXǗ6j!m7 qll+Rv'0ƈk de+PU|tZZEJe^Rz5$U]({v޸-;֪}QNۛ>u/~ыѰ]WW>Rg:S跌]x7x3Ĥ@gF*lVٓ; G IpDkN/ܵNEl+?BrUξ.U-kd#$YkjIV]]ӠC.b hkqu)d?S G]l0A$TDBBôuNfO_ :^4ͦ>~jTs7UlѐZm?.xtÖ׸vJFC1ޗQLo'Uc4#2S]Ӡy endstream endobj 144 0 obj << /Length 1884 /Filter /FlateDecode >> stream xZYoF~ ڗi"-P}rHVJۃDˆ-@1=s7d8>'FJs+%KOrNt͉,9IE>ywUr KҶ[6$LYl|:[.bd4-'4*4L6E=[G²ahPQw5UvMٮ]\$"v/92I6^<6|VY_{yw~u|BwtbMδJ$Q9%4qe)O94i;su7Iv]Ӫ@;<.Ub!S)(+sdpA ;Y5֟9u'u>2tx@9$؇ʦ=Dwc?p,k䄾{xu! ;teJ E#m&reᛌ˩4Hs?A@a FeDqC%0s'2x8ښ)zL(FiȬDr.0 0ѯ?aBT#j,mjUʒKa8@4{)1 |о"螂2--,.dB+.Za+eN5F /COe0F qKbרF)N0Tb Ȥ! z`3I6Tk }ӯqr[{LNk +O\p!&" pH![`C`h(M`K@&6@%%rMM8?#%D[Si]@K;q[y BH]m<@H~o9,O);!Iݼ}o[#:FdBQY{1, )B@f%!cYK?GqLZ6N_$lIᚣڋm H@ = _^4~ XteS|/an91uh@T5wǒǞ}75V"̯aHh6:.ah_K Wv>#FnPh0]3GعWμа^R}$"|y˄oshNTCp0&4fiѯvMb(#кE\߬.qwFEߝ]z;OAtWM_mFfֽ b؝bzU[y Ԧ]Q|H'k#88Y\sL7muLTP-5bHƽ} M9khG_[)ԉFD0hp[h,tVmExQkxbSM|IfotT`Z.K=~ CJy<:-OU(f~{o?*y?mqQ5$8NZg:> stream xo6=a Ĝ*m oiA-lwGR8k~vҎ/&uCh#&QtTGS84}" L QF9!o3\GzS) !;_}5J&⸚]Xi5╮},AJ&hC%3ƭzjn<Rvp|l V)G`f:ò7=KYhrfzyachMdgR4A"ڡE~TV$[#CTCLkvQw! FY;t/v:$S Wutxqޞr& xlN0 6~B|lK17ruP3{n:Bb];B>;dæΕuUg #Q<\0\PZ'awZ.p{kH`)'ҾE@ ` F)ڄ5t0^Y8Zp5e䘗֓ ĞU /#e?o#l/>VU,>Upq7mX/OSkPI' j-@ qLm|ً OCX҅OO"Oll Mבk)\\~Wمak6 H=xNp0Mς*w\GwEv(rE( ?H4Q~Nd,a+> $(2!LF\p}mei8hΫb_-ܒ< nɠ T=oD|,p.YT1v]uEs[K7kܴ)Zz# DXaݗ̗ܗ—җꞞjH{A\" k56\SɁ$*Q ebhRQʘiLp" U0FqT bH5,HTk$%\ {y"eB )P{Mלqvp,w\% u&nw6a6yj©5G @눑lnhe!(m:_lWit$\4ql~|,iU*)3W7gbd^ͫC^MD4Ndg۱q|m>=?ɉ} wkLkuk{"&7ķi48srk=զ>fPH'(՝yLE,c =1 endstream endobj 2 0 obj << /Type /ObjStm /N 100 /First 793 /Length 2202 /Filter /FlateDecode >> stream xZn}G@dx kxm$0$Ha,hGRS$O]XŖ#KHP, <9AW<%rO?#]N+^?^.U&5J8k P3e3`էѫk,麙Y݈>L/:Z]#}7Ӛ>뺞Ң^&L3kg3y=򲾤zdL%Mgz8yrlutM5d/͙9s7gd%wn- ZӲ}deTyY{RW?A9]qrbR Xk34HHp` "g IQ)=~ GDC#ЋlPxx( w @yn(~p3Ec#d/P"%ݐS0$ `{>A%4ɍnYMYhPlb@}x @"6ido"`aXQc` mIIY # `Q?!w8!(aHvŃ""l, ll`ak  xֿ/-w6=nzMo^umR>6<KA->!Cy kyg^ 媮xLAR\GYygE ׅU!Q}|ʽPwY7W08^^Im<{;?کrL^koo{ggmP{O G -y`K[u桂L:|Toǥ ٰ~Xyi(OD/d\!8<8GpJ4((faj`q*|=G~ 6c8CXk4X葐GlhtD?. 6hzL-+9陃`EWvڣ /T/yNkƽCQ'u͏x4S %6knjj^v91H緊$ldO6 ("%K 'ޔnJ5ozo:Wbjڣ K\'q]T^F|Kls~WNpK95|/'4?>4WI s6!oZ]k]zx> stream x]o6=Bآ8Y[:^nh4=xt,lyt ?$KxON`Dr4"gCrf2t(vW/ E"Va_E(DD O{Յ3ʑԓ! :RS2n2&iZdx=VPoGIlpOE`"-GJ-N3%ޅ75<9j Sd]v,^E  WqpD"삶| 08Kx:=N `Y(zy[(o6noaw˪Ių)qcPM~[#雉J1^7MiҸgmp)l]|]yY7~gpLسY˂ nR; :n\/XLgcg*DN (wOde2Sj1Rֻy%0ߦyNڔ& йߞ[[󽣹LjDq%lҳ{1#JQDk/ adhPYڤTUϕZ\+[P5/54=&%t^檘!TAh e\ $M!Ƅ&al?gAefAw ó ^#7qᰰ<0H >vGB"!i(#34ap&@(_eeAA \]iI$#aڂfYZRT+2=gQlۍfF\B_Lw&7wCV5@GqY[@+4 8m\=xcpYE]]xoN"ZsB02ףTEy1TjեP&O#͈n%pS5ҶRcHF-V;> ͧX> stream xZm۸Bhp ČHTmrh;Ph-"K%vp({n6Eqbd vﮢP˒ ۣQ}0+EE*If+썓e: JT<&_x@){JJcO҄hw;/WoIdHyEk~ _MJ0:j;|,b?OØT3/n'PpH(r2H6h 2Ў9RQcL@3)Qnw cMQ,FvF.4=i Q5ll#NJ9IP'ڝN<>鐘")n' pTU1%=~}hqϚuW6u0#sM{B⛓G P,L>?b#&}]Οm= v;5ys.S7L9S!YƷmEUɋ˾HP.*/*/KC ~:T/#=9\26.( S#_E8( tjDM"fY+Pݷ Bs[{kng]s9PZoމ(  h OA^d*TeN\ucWy ih۲-dEx,g嘏D0L=t7DhwgLӼ+:41cMZӱ֘^ضLQ^ .%Kfa xƆZl uQkHmn*†ZgMY, ` >Qn;y4*R-*mоsf:-#$=Hflմ0$vtx>weO!m*!y!D7weh5u70ֳkmQޢe˺0kzP?ufEdfRk@^ړ-3m/8sgeT)L3~e,L:bՀÞ`Itd&Σ) TnZQZսWa[Uo(ZBm#|z-C59f{j\rdɐ L<\.d 3EfHL`ń_ o2p cC HWX."STG\D-ZUB*]Q^ll(nGswe})SQ:X`o@16{+)K RD!%nJ>4&0s_;z ')M? ck^@'$ B mÁ,P.O5N9(DE5KWn̜$7GsZF?vYBC=b^{"7f>U_Wn0q2zF̴.ґr@Ldnȗ.o?bM-SydR-H[zZxq휭So#tum:_rR,f5ݷ.wɑ42Ҋ"hG5?>K=,{!gC^*o7'oT,V"Vƚ7Of~pPS@dmgδ7ҝ)!`γDR&%l΀~{}*z8ݽQ%"R}7$"J/XϩhfHCⶶn7k9'>;Z'sM}tfslΏ!i>!y~?ܷla32YܞXy1GpGgG~vG%.OZt&(XD.">C BX9sd|vGyG<&L.L.L.L=Y-ש(Kj0d$4"V,> stream xkoF{~"WSR~b }IBΖEJh?CdmlOAtHEx(vro+F@)4fПO0`:r1v#]~& <ߡ ASJg~(mG]}O  f'P `!"a0,v.&O>l}ϔPv)'|JRS,qyꅩsSrZ6yDNԾ\ֵ4Ec*UR4Yl2Nk;0(#;٠;܉hU>'@ vxZg2ߧ}IeH"띫U+kT,'0ݝGdеA JfVyf_4?V6 \I3oUzj JA aoj7a[&E!rQ3qAk k lҢLu)[Sߊ22mIYB+YJ`mz*klbLk `ERصN M?]g^^ )-(*/|pe Ļ;6Xce8Y2F(8+#=\X19=e}Š!M/񎀎 DF_(N粔y/7iX̳V8WUų4ېY{(>r>F042G3v ](K .G 8 dmز׵Z჋yr!KUq!BqsW&^R"X-e`ϦD@3ݪi]X ]9웽Ǒ,G2ǽ.xa:18if?1z[ 8 rf[AO8.ďi;L<'лmq0fY=C=D0g0pMsN/a'UE`z|S"uY0^`.\-^3=VQJvgT\G&)mZ'4;$̡kTgȴ4SQ݀RXYiڼR95伱 wU~nRIW!1ySڕQTD MXBmJVZ";NQ7yyezn@]LOj6Q$0WPD0d^=J~@b!eJF+h B)4I*Ŧe-%#[%eHv"VWRv3\BfN'-_Ą@7'sH:S&_TE & rx Nj%\qI]8,8y ͒$󐫒~9VO> stream x[[o6~ϯPZaIa{t"Ա^C%]kwrh`^tD~B~MrE~# ʍ4Uҏw;DD2Ȥ @& Qsst8j͎~n'AhTfYh@͛HP1g4 7Btr8bRNpS5Qz8@@4(1 LyA$@ `dπ7-uEӆrICcBl:SZkWJUՂ}`;"͍lPrQ-A?zMk#P% zH}໺ ʕd\mL-i@Pd18ua 0)B CXTc$4 BhDA)@6.OA\0'nw@Mt. zR^s Ԡת/Netq+nmJTT?ڻ]LCp?C\`ܨj s o^hݔk_N 6.X(kaOzq}MeLԶ.VU+al4% -sHmfek;} z iu뇧0cGb}! ӓE/OǏѰNw$WL`H/s9gqύ'J<NRKl#AN?j@st8o:iGU%F{AfU-&7/6pvF-~{N[^*{EUǺ??IHK]OX- 6R;ڃ֋=u5w6z(g*a' H9x/m$I'ש7mEW=?!Yr_ʼj6: ]j+v^kX[! 6'r6]k۬SSN!w(.Hi=/ĩ3#| ֫nltole'&F粮BBIjn1xS2e'LJtOtOgH&)'O?zsJI*߾=ZU翿LTYI{.,_1QIY/|V1dӐM dYϘ*2S)3nfnx3{cO7t3H?$I2S)32Sg?R ųW+㣿@ endstream endobj 176 0 obj << /Length 1763 /Filter /FlateDecode >> stream xr6LS)|ͥmI6`5E*|绋e#RͱG Әzd範mp ,|f\ɔsʢqF4LdlUL.Ms8Mc*\&|^O)\=SNfU0 .\Υs2D4+iPQVY\2KY)3MLj#ۮ7e2߶\Wjw9څ͘mu}6@[&"y'a2u@S-{NlՊ]@cH@@ Ԁ0*OVz/%ޛ EIRŃݎe!ή6miMhʹL'@ɯշ xY&:S99 >3ӷ.,O'7I萼&â^:O|`Uknce=NhriZz D'>sS.iP{/ߟrvo8Fy;TA-1F:'Y2WW[ ʅn: 7'}p4}p~i6'ˋZE/@#<_?nLv!vuCEf{@\gߤZ@2B&B/ƷX4fgSH $/RsMBFq{^Z w"AK=s$z'fN .5$fUJR Ԕ:qey]O pk ,ov>Jn&A =TW)%*=T!{۪* p?xGz7eA$a%i7q8r*]ْZJ,EmD-+7i0|Ukdj㮎x&Clcන9(X44e޾&@!LOI6EϺJl-| {iS_T pɹ @&NY6;EE(bP%EQJ PBJ&ޠ즈*֨R3=nqaT ߢB#C6YJ"mjhi/W.ީPwR+</ߡeJqbgk.1XlAZ(k$~ Kd҇%mfVShrQ ʓZTq#DrpjAl}K9vQWv2#>u Ŝn 484,L{KDN㐩gM:rڋ ~o=JSK_;Y#*,ԂpAktĽyܤSszq2xhj*Ƴ&^|G/;¼תq8ot=&ֱ]nO~*LYҳ$$%!TqWUT6I11vQ/Ni.W3q#Z+LKcO&oK蕅@-w5yuh]0&LdZnʸr.]?ApY!?6džؐcO"?Amhlj`Ӹpyp9_\\_^v4YT~c9MۘZ.ՅX%C endstream endobj 180 0 obj << /Length 1546 /Filter /FlateDecode >> stream x]o6=B@n#F( mXaeyP-U>;~(Þ8PD"'x<>k"{^}{y}z{P] CN0Pzc 1bx#oq{Q8|Rx˓?vh2/D“͙˓W0r%%{Cdޕ,Igʾ?%u'manMֹr @ TH?Gx@5PMSx(cKb/t>:3̎٠L/Tګ-S! DKY+}0! (FsmKjezPmURh%fG3!|c [P"FLmopw:5dhqŰ P\_P3\4yeR[U V_OA|JuͶ; n1.iQ#>[nEubp)R(-*ϯ\Q1HҢ(4aamQפ~sogQ_:CBZ+^N⾓}4qMQcLP&Í(;rcF׾ZG,g'܇c AQ)qȶ/RzFJ66V&[Zyczt>I:?'\?òLKw`\VuG|hi!d=s}*zDG:7̑θ':"S oM1)7E oyTP`%8QWmJESM6|sZȥ9+27.0A(A o<QM2lddU!E1sr 9CC#DB#qR e28$tsHʜϛ'$BL'Gs3A>/7 endstream endobj 185 0 obj << /Length 1298 /Filter /FlateDecode >> stream x\[o6~ 0ט{8xlʢhXSidFjdi>hLӮ/dyPV5w52T#Ӂ")MelX!U5 A'OjЪAhN3ӦhHXZZ6%1'6KL!9'k焅,cо о x;sG$zd,gxNY>u\)&#"r ??,[”mh'۞fEI*1ee9<"9WՒ:!`3P1g3,w9inVB/"/UyY}%n?+!}1oGQ0$74_s*i1Ilc49Y1$ J7j6C:5g)ζ{RQGTU}SF tPK ΄z|:n'nPb[+S{itwA/;nN>4MLlGutb endstream endobj 189 0 obj << /Length 1789 /Filter /FlateDecode >> stream x\Yo6~ϯј+Ecw>{-̓,Ӷ6PrR9mc%Gf88(z|}p:pˁ~B?/{|p3 v;,  xq&g(&!!buwgEސ?u]"mt= M)2838x_* F, % 0FiD6+<-&MW@}h0h.QsJ嵩2>p#Fr`nE!Afu*E/2*BۘBE@S\Da5EJ\Uoy` mf[0,FQ8;e$nD( c˹Ur<+]f$JVvqẙ.%C_a?Z2w7U^'m4<'k)2u摴=_NҎ?訵n o;ܭ=yvOs0&AaSnԀ!"ַݘX߅*g뫫#>^sڎNקR#]jKXNxOI4_jŚ%[2fyy9D&l(ekXѤA\dmnވ ze6=X!ƪFckbEє]߼'D;3fL}0}{\La4Fo9T0smIev}DRɌ3 `_$0| R} LX+&8fyx+B CLM/Ee.4QhY\*)d6-Q Ps㶯(?]:."̇!L&H!Cw7Ob|[ܳͱQ$ {(3 x[7+kzB+*~rOܰ4@jAҖ"\Yʧ!@?J"hbحXdFuQ*GU K4DG~c@gUG`(KpH&6։ U3La@xM>{#!<3 2XҰұ:i5WDuaﱞ,)` nuo ;TԠR$F DT?A5.E }!u͹FQpDV;TRR6ڐ4U![׸),XI"QҭJI`nKC첽&`A|&mn~% C_vߎ̥8bX&c|3c >bUdN*!mΉd\y̝3ش##qIcٔOwݡmVYRi(  ~ѡk#:4vf +\ M o`EWi>ይ4&#.B\.Pr o$?@agO٬u(e04-wLtLtL`\stPHL.iI9G/;sy3YK1t|uLI<* A+Yw9%VNݒ<`n>[_x;3-^01: *- :hdhZi[D6c z>~L;nވ,<*fx-KR% ~3/ڨUb67, PJ6ws endstream endobj 195 0 obj << /Length 1904 /Filter /FlateDecode >> stream xXo (u8m/.-rW}$Ɲ \`M% #);T2pA>h_;y…dܴ7WgIK"yxXϧO$QBHBg8/RArEQ4jMt{ɐNy尝mX"Tz?{XJ&cX $qn'2 daR.T*' VX2 s$IM7gBUAKJI.3?QnbAvs (d 8Spe>`K&x%YKfjRyՋuWe_6`"Kۦ5zAbTqsUqܦ]Wk74[KcZ Pc<y^mI} _]e_Aٜ:b|i?fNއ sHFekCp2>N*({|kV" {+^;V;kyK#SCiNQى(Uߖ^8Ⴕ%#5)A?$.<ɶ{۫I>(96_AB቏I+}e5rXܸn=i{7ّ[;WV-|}~@.O!8T( a:8\vRTǺSZ k___]^+^c s]i׋bKgvX@XBI@E ǡg0x&o+ޖ>TG]v9_23 |.\ +'آ}T~,d5qt.~Uve}™ͮ7n>Ko9R+}.a`Lܫڂ5vtЍI>’G羱\~2*)/wm u-+;k^EUPMu N 9nWYxTU`HYkV ~̲ܷe5D>6?,Pm ?twi wxpLg<7|F1`jM]|znQrn^c<"3B 9U3#YE}9 AҩxyTh7`߹HuѴۦXO~KRxٻ*2BL+?` endstream endobj 200 0 obj << /Length 1342 /Filter /FlateDecode >> stream xX[o6~ϯ0pXd;6 [fl =-Hd~ENbK4u.wGnB~8z}={(Li%)H`!\DF ,n}K frTzş\O^QIJ|kܡ {+`AzxITW"Dg[2" e<Վj`='s9mc^* ΂ؓνfr~M.fuO(Lm^ KmLC#l,.~'Xs0.m?`z @&*lM햒yQۭ(4Fɸk>R}lWDD cg @ zĩZ #Wci_h7 -{6]}3yy PP15hˠ0vN3ke`NCfġEzDr9'w[#ʥE/3hJ`60ښp RqK]Uuũ$YpgV0^͞๰:t$buc HJhf,{^ɄlBq".=}c*A)nNTT (kQ1&Wx %XN;AfƓ`8~aYN*Dgoa**8 .ߜڎ4 6@' t/9ڛ,6[.(b9}jE?+L쩱kIOk[c[ް:!Kl7kd8/><{+3^ҫSVT+VEk.+nB`n0ȑxG M4{eg5Nԙє©^aF7Ȅ#(k8)Dͻ"ǏV&hс֭ VN\2pBeө)It(EÐuLs5ROsmJn(9kV/[ XO%0rlJ|7hCOwI:{QLX]080LL.jq7m^a endstream endobj 204 0 obj << /Length 1084 /Filter /FlateDecode >> stream xWQo6~ϯ HXd;:t:XntHFRqw4IInz)Q>~w`ܜ4b>uqGx> iuyӯ|uW4>^xa9&Ẽ"^nVdR3!01ʶfB->}\K3fYk-/@Psk*qvoj+ yY!=0맀- 4<|;rQf3Тa@ znqчèbTdkZ#lW;9#̠`BxukItSAr",)Ns QefɟhͺǛ[27~$~@(%S̱`Ô<wW@R?LO83*At.$ł(' Jz,Ωދ`J8`~RFC`H Ka` ~. ˇ҆K 4b0S.eʋuy K"%؏a>ŭgUwPG`;۰IR2s, W Z_TȆG- 6lu ~U \VDՄIAL˵ P`xJZOMGD{p›"ܱTBS^-j+>LlMҁ> ,!M۫gP4 V7y2 .>җv#hSbaؔӌ֝5|/s41w+cZ$B4[7{uKwS;#ѭ^>Gߍ_p?tX&'ݰ֓i׵.suf\4oFM t~uOhlkLd"VP N9,CWO?Q.fXIx1ES34?+,,'DS endstream endobj 209 0 obj << /Length 1085 /Filter /FlateDecode >> stream xV[o8~}*nv4Kè3p [YcشI̪#asŶax~_͙eBW>,^, c8F;bsP "Xx8/֏D/?][>Oa 99]۞@3'cIfܟ7Oʶ_|K~%/' W˵,}`t5c92LEV(Vi0m=/塚=(9mn=v,r8 ct{ĸJ+ X801__2rmeI<֞cS,̫U,l qUUTUƸyi+`Ȝ&6 < u֦3@R 9y](QQYlF:G6rEQS#5n.tOGҁŴRY *ƻF춹ċpx}w<r~!l@ΧU_KCcK9rBYT‡ݼTDz|YFX`x~'\ͣx:40_fal{v%aW@R0V&Z/e8d*x5^]Šh-6]ͣEW ^O'a2]h+TnYmht+@yќ5C rZ mH+T]*GfTY#wLlytڵ|o+oXnw?1鬆XNb^墮.pZ꨻iB6[& >^A* um}d| b8ˋFtM<4 ʚf=GO@w١jqLّi1ś <- 1DpRغM)Ė _4  xtS2Ӧw4t5쉖- aGA m[[X'(sd6q}*b}v(S`im%=HZE YV/g4ty!F8'>cz܉6 endstream endobj 228 0 obj << /Length1 2120 /Length2 14799 /Length3 0 /Length 16076 /Filter /FlateDecode >> stream xڍP\ nݝn 6K;kpw .!<=ޜ{E0{{U5,@i3; @BI\ƁDM rǎD tqp$ވJ`G=#+`c"4YX`G+dmV?_tv~~^. 3G ᭢=@lyO :A77'VVOOO3W0=fP]<$ƂD д[yo{-xАS8&+M`{8vw_@ 6;89zV { @EZˍ `hoa73#u3MZ\Y\Aid+ۘ-%@G7W-kt9ZZ%݉U7̈́f tp _4re~vXo|]<7w? 79'h7~{. /7 ;{kK1[`//37'foU3п`+hۜӲǿwB\,!7uW-+ߎ7s{noW~K}`{s3{1Gk* Z,l^Z= vj0uYؽ>\v_.oI)G _W0sq1Fb{[%nn/9ZVG[M? JeX%x2UAV?UP*(XU [? _ziX-|`הY-Tz!eѭby#_l?(oJl &gdgo6?X7Eorݛ?Bֽ0nq:V] =fVϬn6.M'oߦ&xGw" wߒN?_?\@iel>̶>NȓyoJN=K#|*}.bk;Rt7d/'mjO~&{H3ӟOH5E^ {T =e*OD,( ?W1`\:O]`OLy>s 3oL>Gb_M*M^*}|̉Y_4y%߲x+.t3g/=+[G&;jGy s/&EHj/>\BENU9"3InD#Ӗx h^E9 |ͼPOx/er 5N5g G)mÙ||$*8 `;|rEȪ( 撳{زep6.V@f\)C d(GSdJ 2V[[ff9-5ND`q|. ȲV2oVbWgzM4RR=S'7ebGgfD0C@i'Ep >ArNnv(epm߭Mhco׋F݁m-eb:93}Vwhb"&}J-wqVe[=&LIoU&),+ ۔-}Z)hS5.oi%Ge.bNYup#[곧&0 A5ɒ2c^[䁟^AH)/óŭ}>;6H@ZQBH\q^9Ž|׶lu#ԦO$~x/ !r){(l/V(.0ˋ0*듧qս!hWɂ>[複JfA=Oa d=S9c%P]7|P_ZK0b<kd!941w3*ZIіgMɜYUHsjEU\~W|rXEL`M9\g8OS81GfY{M!-ʽ#=Ty3 L'%] n+"݆_7'6[c.)"mFc[#H.]Jm΀CJ$Bi!0>ؽ#@f 1 %\s#/M&$qz>.3! 0%~寉 ImU}H8JlVYO;QbT.ݰwB}<?a%`.Wl7y9D6\m\ew n6~{icM=Cq0(mjbSȲ~D@ÈMU fe&IG59Rך4)sx~Nm_@wGmT^dPΌ[s򍩁b'pw.3 BIT1UtMiT6]dO\bX)6= )&b>w8T$ߞ ||YuИ;L`l+VA-,9lZw$?h*3"z2S0r5Pm ϵ}*0@uJE׺2w LE][ƟD% {)n8ĻB(_}v_C *\iXߎ+n!N`*9gu8CڨϞ@W(0*Ja񺚝CG_XqMX9;層J甐ydguy9AbXdMSwE4堊n \oп:.w#U =LIY$#9 VSR 3;LYis9x_5Q&,WrL ~4Tj|/|s!Zِ;2rg \oWaWؘ1-ZP uؒwz*ftO` ~)UW/$DdpxJ c&)UR:R(|DS$ScVa1w|JO`^ SoJenv}tGQlig+NY/{ e69 R;#}.WQOkd2<lshX%v:eX/E++yR"0Ԅ$yэOa^6lF:k \Dz4%ig@n8F^IRqKK%."_UFѧi-pUĮqkBf;R~5_gn ZTRLtW#jo| G| n&HQv1tM-j;֕p~$H!}B6gm=Z1%Q5K+d${ڂ]Un=a>_mvT6LW9h %F+&5V΀Oi}B`uꠘM4byfbQ}W1~^lui䏯 8~Moـ;AٽwLCID\#A&ڰ +H7\Y҈I$_z3M*XREa ۡ B|,U3gA'>c69Xt 'fo%QϫUPWQbXV2= kY;rCS[nI;8l0 o K>wx ߌ_k~Is]PZ}Έg5YfsEfσ9oˬW jױنoFtqgH{fEf|vdsD \Wec:uuOA cucN_n lN{晍R !}4Aݖ}t+oػ9T3`ԏO*tnEblE>qpda(e%\.CRSݨVןuWV#@d4YbOY$H'vI֮WPkyzcpĖc'9 CeV?66_ ٚ2fq{3 /XgecRw90E& ddK< ~- @!a|Yp/6lw;/ș7!7XQNGh&M̨-Q:wt+O}".!o cǔs" o3_ ({-^XFV{lh;|neO:8X:.3XGxD, ޗTkRc+I lQslB5+7}BXa9G;9 F딼bvD$%سEOh?,o/r{A+\]4mu'x*{D^i &OHXL¡'E΢uuxV. 8F}['}Mcޖ>Ӡ&cMj'<M9 }Uqo*\c瞮'dQԞ O|ʎ1N%.هy;0b,Zs~,୯z-.Ċx-db&2bڃnF1ݍ䈋lA ?`\ՅdT͞+5S_X#@\~%ҥIXV>zܜיb#S{ )MUx[uhR?X |=O%}j+ &MW˧}faZ9 \$-ؐ@9{}[wC s =4v7F@="XK_q*R^jvB9Ϋ˧ϡq!I8eǥCˉkj~^U >#BAf _,NZ1>hCҳPҎ4CHënj6B~>9,4Ro ^]|XH#KLZy'y3d 8m|ԝ %d}|>D?DZ@U xܩU,"P$_%Y#]ʹ@gUr;z8C`ߏf3蓀{꧈&ME"e!F.ǥFWo.6_I樑ƽ2ݽ͔)/,f LJB{FDk)YugްjiX_G1:Tj“xm?$cvH\C^OMᴙȔԇK#:f#SSo^  S\O9ws#uJ,Mj.u =Kd8Dd}U n(sXCjX0Qf'.g91MP7yFܦfk ^#w ||-KLy-/> DG*0:gN8UH8ˮ?e.]ӟda?Erg@+g)M&vÐ Ń|aEKipO2s84ۣ93mcf6Rx֜d=`䠘ORx Q<tlZdǫE#)p`~uRU!k~R5Cz\`8U{0ML`Yf.gfz%UQa%l /N/w}a?M"0` H0:qL9O؅~T>Y5F3i6{ [78 顡 g7 & 20ڷtX~:/Op"5ý·]2ͨ_څbê A6]Za&*/3E άՎX@]ɹ_Dy˅D$'+mz:{KںFQnsᶣy |1R^(["i\pxhU5W*.yj`h+c(O0z԰ƵF0~Tr] ֨!l ٶ%yx= ,%lrڂSwObgDC!ߠ TgjDv^CbPC:'=O(ɗ#)-YǤ!{2LKMu[󙈟75J"8c| NtC<1%T0gO4D^ّd.Q2Lj1\ܛx̀]đ -~;"T&R-qmoVC3w)_^2vjnO4;˨qg\nmBUX̏=J.q{mc)c.Mî$0fH2PGn=ѓJ2 `Ikׄ!/IoCf,=PuVk5:J `eU>QG#`  % .6tv|"P 6ڲ&HuPoU07utN\/A_DAoK0c z2BV!~Ǚ+"FF{~ nZ3>4bsR,a zVMp:fPӹh]М|i=q]=u*6/޹m =QOʋ1aqcNE H>hiˇѼ#hw\ԜhΉCC:EHDAf%{\{%')ثEw;?Źэde ZsDgUp4s-v,I_yVNf47S5 '%DmIR4Wv?QfAK>amqE0TxUٿA`m:!n0%'ZMB&o짠'1"E&ֈ #&5S*TS֓ X6&ْG tVT^SKjnnjY䆥U!b(9Ut41e:`l)KM ȾY`qJ&I>l gJe#?GF6e3gY`HO&t!>1|> j)Et V*Dv`Z#ۜdOgR;l\Bݝs _Ɓ:"ΟnMa׼ƚ Ƣ O`po, s\3eO% _Br rٻ =bӄ!3+WG@|:٬03Č-.^$V~*Vwߩ3(Kh=#u^,ݲ1sn=<9Cr&T􇬆U|f2\ޥw HڸyGk!YoU(7?0v㮫 yMNF#vBJ+_3Bp㓸,~,gͣE;V\gԵ[+o&^^cʼn)s/ AC AY.h͜uEi1nBS@AuM|qRߜ׺#un䴙;(;` Gfr2v:$ x]PiX\O?3ӈ܌&a(NddmK!ǽۮ%>`bF7i=bT8*lZ"[hӳOy2|zhN@&5:})j_; :9^~Q8wGBH,TIբgwP}wZ -sg}i~h]#Z^Q*e`7"nD!L qa|~ݲYn[yW*(x5cˣv!z.c.LT̝jž#eLnQlAX|иg2L""A,rFT[5Ǻ9z/b/D?s5n/\;5;ADۆ<+2C6ruXr g8dߤŰts.n թp.0Όͧ9.4C{e0.[WS\ Gaa.[lTuaۜ+?dx( ]QC_/jbK{KBi/)+ c8ss]9έPL+9ӋOtU8VhF!O4Ez)j5Ii5GA~с˰0 ]ƐB7yH聓Pg![qLk[pC1ꗤT͂Zq<^GߋDAR. ЁK;|7P ~^n^$Pq/wMF(r.僓\;ߺ/&lrz:G{o(o/aq҉wyL/T`wAMMM.FӲ6ZsFWߟ~[]@Y>tNG@eBG]\$Xm<ʌCu? @;$MpJs ߠ濠$۪ #.E7n&3Sw6R?>R(Hʷ6o'eM8eH$¿+^'H"^5ANԡ=6.d|)V阭ˎge W܋5$bORȵgT.rb%z?QYWkW8bZ:e`"M*3s.4'8Y+vgsB9_]c2i*$)ٞQɛvE:4a`5*MG:Df+h,-`C:ͅ3M՜rH'TFY&:VTǕIPdF 劧VΙ`%߻ae]:Z[UwS#C+uzW63[$hk{rBUzi4` zh?2\c}bԏΪD(3Aڞh$Sz]54yɂy(✳Mо G269cUx0iE+?S6 G (C/j wCy1nr]9ya)+EV] bjOE9vLF9+ i49yEbZ<΄G)6ijzC~cJQmk$H])Q<<8p7/}ݹQLvWD2hQq BR(ׅd#}O;V5LeNL DPgׂJ␰^ hͰX$\@|t֕PnaIhL*ٻ=Jӗ՛Ki[=1`A_1bqm±*^B\>c0' ڠM̳PtdL9P@]ʕrrwl`ohb#oÏ,anľd !X+u^+JԐ,~-AqMb-|vE!xa_^᪜g'7GH͓J64ߝ18qh86<ı_\\6;~~JQ%O.ҲR.f4Kؖ,^z]&I.}1`N9~_^ЕȻodŸ9FgLɓҠ6"b=a]weQ/ZE~~u׼r%0i\vtB@F,.2¶'PU<7~CNeq-N\nJ^#LP\,cjAQywibTkuK‰~뵵_dp)4  sˢ9:!aW~T nއ_;eI f_ 0t=\%9iŸ[)P-,8 Mˌ Yh ڳ'u?fpڡ.6dOMe^-kS5Zc {ӡk݉$$SV3;`AE0($ưDO#QtEKƤ vO4BT\e'͜sS$rse\}=Mhl9+T~z%}QH$`lhޘI.9j$\HjHs2ux@ pC*p<׈ZjV=T>yveI[p;r `L Ң/"GvrFusLj} qd"K{|[x`~ K=PMg8;.,}U@O,;H(a?;?%9tc?9:3R&TBny3,p޺ĕ}&M65<~?/"k`^8 fH߈sQ/Pm!K f}xjC paρnX*1&xgٵCj6DSgqr+D!LT[;$w9EyI7I f" 04־qx\UzBD/S+"jX>N1 ^07!P VK/ rVbn!/2pyxQMz2ݵ JGQO4QKտ6֘Pt*cA7жàosbv[قj?9nI-=-A.| J4^Har4Hk&.~ev QWZ@qqۢ7`ǵ[:w{UJG!KIBl&ɷ Ơ@DfSGOVi\u:/l&Xe?7OmzJJ`@ Yx w#xkb/8<9Ӥ`$r2Y%ms"d[9ݍtAٻLye~b>kB,4!zqvnbϋ_b#_ v!Dn)GYİ7 ;9w20%^9iqhGz{1h w9_(dJcGCf7e(  8^B' S=UǨ|87Lk<~Rf,lH+ODY5B 揝j~0}/Wʓm-{? u.KX endstream endobj 230 0 obj << /Length1 1450 /Length2 6910 /Length3 0 /Length 7888 /Filter /FlateDecode >> stream xڍWgTS]I:"5*zU!$t* H)REz*JUtѷ}wZ9gf=}d!la)*#6a"fPDB0X "@-8PT(*%'*-'" DU 0{P IH7 ]O PTVVZw:PA@] ]#`PϿJ*8a0nr^^^BWxO8h(j56P {8!Rn G񂠠@"$=Į4AuU CA>0#t0A a |'bՔ NC0h!4 kJ_e#]] W*0> v!~b&l{@5UDa](z9 Z ;ۍ# t 9@/R?4 Ġ<~E** aPGX7h-%(P gHZ=aee7$& IEŤ%ҒW2?r5H cwꯦ=dB`(i;b*wOjpo_>b`ĪPs2VF;`Up2$*!$"VyC `;?0kY""Ê{buUvH_BP()$ON{oBH 60D:ZYi0%*" cbY+S (PWKv(Vك/zCHGveu%J,^b{U E$juU #o [GiV i'SjmKYџN3 B8b5X0lҗARohSnςƎ/>.ƶ})wi-` )v ~:ѓ4u(uFCTؗf ]j\C;)P.@HxWbU^1Q{ TvݾȦWZGO L_|ZE< ㏯bx8~hb/sl\XBJ^eW4AG]. KAwGfiŹ 8>{v֮@yU{@rO \dolmpBﵔI]`}'? eA[?‘VMM}Z#ɮ|$B$'gGژ_A/9o5^O3/k%,'5+H)E3mipas7ڞf-FX5# ӧ$iw7⃩> Ai |FE4w*^M|Z}})DVr-,_&OfBkj܌[fPSI׽c&kwݙ"ar6KnqdUG$J>KilHk賆Os)!Ymeʪ|f(^;ulBqJvjRd\}+[$v&;IYN7w-og)LcSKݍڵTRk7:殙ݪƤ&J9 ;ƥXrMhz¡l|ѐ_ߐOV٤jFZda)'>4sKPhhu;$6IZ[>wNhnST_; 8Ew{ k5襳y9 ͇^~/5ȋ+rS% n0񘄰<;ETS]tli!O[I&lQn0T+O@2Ak78PSΑEu P/-~z3/Ǻ :q!dhk ]-kY1w^Yݱ VNPNhv=m]!;Y@#rCP{7 M9iF|}ؠTQ5^p܁\[)* s[N͖OU(qI7{w.7l%L $M2yz闔+LoWj/ {ootV}l +))U锥:|o_6΍[?n OTۍZ4i}Az|XC8JԹ[KТ,"M|kvnUo!p 'npFZJiZsQDp1jq~d%%,7e$sKNɑ$bW,we|t~BTD8-ʫ_ l%xqV ssTcۇT1omdkғnP~ͶmQK8Sɑ{wҕQ@8&jrf؃`a t`ݴުf ;T*a 7B._i 8V2TrrTU멛W_6\a1~OF!?L6puoS'·s,Ec+1ak$MBs]ES6ppXKW$f,Az%K30P+U-,^}`<#n|I[5}6q{khw"l3fذP\RMro^)ǥ7jkTӱ^uK7Fvnٷ6# \[7Rb}"Ye\\kl91!<蝜sSc5iξpghu,zZK۝*jAӹόKt{.5:Jp b=EՖ~ĀkީELN߹yQ7ܤ.N-њ=N9;.!YeH9yC@ܺ SKy]7Zr.XQ  >&dw#-'9׊f֔tW&>j_S!n K$n>y<_X!Р'S1ڝB߈EL#Ylg(UHNJ=?zc_>Ry2mRԮ?@Ok:'k_,+^Mv۰ջ!w9eɭKzCI8 PN7bevTwx܌}]B/( d 6E+ pe?9  fୢ3(PԶ! !ksAsn{2\}_ٌ'{S}~C (d3i;:IfD,S`/}Q_ȌNgOާ˟}6`nzku8_>F[Cޑut*/@εSD]%WHm:Ut{^'2x+)'u tyzޏ Gᲃ l{jIE iy>/yj(f 9rͽP),LaX}?PEq{s^%N!?m?K-{Imb&z4ٟ% u1JɒxL:ȳ]=+%-+i!ޫԭ njٷz:h 5lH,am66m*)"2O?ij6;1`[N>xj}4j6 |Ћqد^fs *WnQ40GCǍ΃:?Q E͛vG.O\O5gZKIwDJy M{ P}AkJcIdWx뾿*OuqD,:kS~2_YkPjI|ҸV=HfbJ :G2eVUcsc{mւBnfw״h~Ɨ~%k727W15gWΒsEq&Bu!|ꪄO_LSֺ:pu>yqo:2T֤NֻRJtQ- EM~h9fu[`˴SL2~yaΩ|# jM#͟RZz n@3 kTe`$V f\V;&쨾*;L#H[}dXfநKi*T(̍vγԿsG-}θ<2;9.WT/]ңxp'*Dq)`Jul|z橝]VIPE\֣xxCl֛tmY&\ nhS/+ETKxS,HHntukC*3]8zֹ'n/)?=3wޫ{KIZӻm~hħFmqw4ZMZ|oW?a^x8y_kaUTHTp?2D[Z%[uJ68T0R\i]f&IxNDK\PKsQ2̄Fiu}$|>|˔Oy_xo9QߺY释|fNԷƉ1FWX,_,ls|{\Q`2.w*A y }ߚcȢa1՛.Ǐ->n< 20Fmݽb Tf=lX18zH0{[A2ɀrGy5]j$wE?4w)ؼ]uVZʰ$v{#?Y3.1)[ɱ#ܡjڙ[FINw:pӝ9x' %j4su NOw~RG4_OJ[S.<{4*k#Z be]uNBzydaĕAzy7]WixtJAY)q8a@ehFy#'K{>_t\V.(ا敯<0HTO5H>ٵam/|NG:zfWdvT?2TyvIeESqlKgrbnWXޣ g'yIP}Ӓy;0@C[.X^]3@Mp0m)/XZp ];""O:8GɆW ~gxf`W|$tI8+[;TFܜwq_Π:` ]x+HEd>/e4b1TKl>7ұ]Y{f+63ՑrfX~7B0XIO%9x T2N[,_۪4ì)~n!^70?q mޏ/O;h?!QrWfFMi2u+A29ņ.p[17MgI|X_4F׭xmOi-OiY`܉zQ,{bd@sKIF\Yj$v9 a;~zfm? z9ի뢅ʷ{59!ųY [|etۡv]*@Z대Oܘ?=MZ{p:43|' ȿpl?5(v(C]/}ɥa)޵9gDa3$:A(;O>iT{`kw0>x/N:/+σH_SqqqeJ^*BG% &n79Jbyޒ~~(@HTnRb-M!`gEۗ&1 Q7A|?_&s}7%Eg0?  bx=EЀ"T#{VD, 1Ԝ\<0E7V qkF8g0 ]2#! q آZ7>A!Ã(>AA#0 P8(`uuBBn_0[7p+yJN7BiF"n[7pFnHm/EFֿ"3 BguF?_zmDT"ҲO=BbDw !8; bkknQ.\<d-Gr+qAK3ċnP8w);//D_Gt7D0g @\0pw#C, 7!|x D̿^z0͋8? ߐpGXއ 7gnj#6Vڋs}WN3w.M rj"9CRP5P#ℽDe۹0IHIPvIhbR%Rm|P>83a!ы^nniaPUVakmM?% RvØq LUldQ5m='j' P=6)rhW@(yͲyQ>gG#aXcc >Xд-}|*&`"Z]Ҳ[guUn۫|/V?apu)(5IےhǬV8vFx]QDaFV*dpzKڻu0yX.Cs7PE0vR(0ⰒoI|{ 2tzGSa xFоēč/MM#?L9by=F-4rؖuzlVBx*e*/EY d=m$OF3cR>R:CΏn=[Q1\#lGU aܝoc+GTC K׿wn>ÏoqSOL,dDJ[#瘟^ʍĽTʽȢoQWȖy=g\W^H]d`֜E0v zAŗ(Q}f$zv X݋3 CnA̔nohRL5zcafLJd o z>W0z)(vԧYM={͕f$g!;9yZC[`NT^͵v i8qzؼl«eі qz΃Jnf깠7dAexj(#Ѯ2t3r?Dc;Pė.A-] *J*zM<%HB+Z=(2SyeQH%M"Gr'y=/uc^GpA ElKqpgWOq &y?/~aotU&cjp^haO[st0 V}Ps˜".dr) Sih6бׂ2 q BmiB$']&* R'DaȖM- {d'^`KM*ZNDo܇yĴ&)]$n5-S@\;擕MI\iW[TBwnI(bwQ"z{MHށ^2U,K&L:yfk6!+iFN:koSrzaU c o_Y2=0o{V㸺`vP/OИcxFquCZqەqic'̽ׯh5flNj I/]CUoœ`C }1HY3֨R5[X$426!ضj~d̩5C{ub.#q~ɳ߭WBКƦ>*ZDGel=zT㼆e粛EKGn={A؎KΫHI #'w?U-y#$jrgO(ƽ- MrW YI?ex~1Vs k'3OK%H:h.##0Rd84[3B2wMY qqDV5{aR.BzeԳ34uCD/';X*y AE.rV[ɿMHFYPش:{z}٣ VA5W?gWQ9 V 5e i ?v׊geAF!bi&j\Ba|3)Sn8YnH;J'(]+B֕<_=괥vf\TF#| `V@b,0IstIƴ~7dXXpδ,;}+F﷞[[&w%b"fc+*# ge : {YG]\Wn\34qN/q+gwH} nf90 c&]Ä/UDo0c`۱/>uʙՓ_k!w nQ]*=/h*I :W'gm3(Z ?-(>JRVR7 zw=L4ФՐّ«dPFȤz0BH?4ZY8ѬL%dJ~cdq24g؆unG]6-K9ԩxMWedJ^!of-47UM{"%:ܤM <_|>v :}U3 Jp14{dA 1_ t;ҵ~& s0!W7O91vs:D =[HSMDL#%3 @:mN-rtOl#+ĔC3g:x^ɼ7ݖ'y]?ne&=$~;vyf.Бfb9tL˼L^c(e{:yvSia$ ֊ "UNa9l$2h;l(TZ`a䗸tSU+c?}e <#l rPG5n,Wni3xBl.R֮O_}wkp%[ j:-s .zxAG%Heo~keܼ맫\j(egښ&xrbI՛? Ў:f/ ѢVJB:wۍWsNP >f^& uU `+4Y^O᧭ rF1q+]ď,kX+zlHj(z_h\Rfw(P@iXڂ e4H;)FmgY_+%l6}3S3I-C;/@;c\C8Dga|:; !l'] 7^Pd-n]O)'5˙9.D]L+҆^RɁlǘjVm2c#V□CT6xa0̔0[˞cuFPAv|F'Ȣ7IUy+^"jOh>Uq Kƛ-dGWDĕEσ+2]s\FwRv >Oqڈf^'>9D癦 ֈUu>[oAZB9y GޜXҌ}NQ )@N1s(,+lJ1Bw./:6ï#7C%ER4ǪS=_뙆 =BJpZ +Лa2|$5sҔQ]^ +:v Y;ϩ?UcY Fq{<ȿp=5 d #0eD+z: \,'kdͣd)C2"[}'h)d=kZ"W9thjSiF0I~1:^O&tuxRE=y  -H 70#hJIWrYazG6ezpsѭYN5WIA襮F mGh2z}@=,d Zmal} \b)z1;hS0*n*?R! 6d ? x> {TUMXTP3לxd@Ϧ(mcH|$'谛`W [@G ?־c0jIHxԟ#0~2هw޺썁!{GqߝA;[75x0|Aw_s]3^hǮjgO5CHĂe&#N(R?hB?.Ȯ cl'~;[7:m!嬥Ek.K*z$W:[da0Y/Y}v#}uv3h3't򒂭OKIqLXn\* uм>Tddm@Aue#\4Z9A}),ݔГqDt ʲqe:u lI۱V=,eV$J[%,$R2#&D8+ H$ψzvڳLPzVGotڟvr>Jjj~3Mk0Ёd {H(oW]YO]`,JM Hv;mwVQ}h6\,i8?Kաjj8}{Bl#윾ڰv}iRe5Ǥ^ҶxO8'J>x1cam&4V~FcAnj减:Á JeWB%:9S=|Xvϯc?=dâۚԒ@6bƇj,IqmW4v0Z-eQzz%r 9t-_כ8t0λUTzs%[R{IOc֙~u\0rJZS?4\PiqcSd۪r8 3t>ܠ?P&fRvK$y VVϫ֜_u>g|̰BhSY$CL{|Sa]k\rg'8ǽHMVqj\ʠ1)t `f g6 {9%PU0a݊dp*{Yqx7u;~JY\^TE Ks7Gwi_nr1[|q8j5،Xn>g"H GY7-:H 24Hь>l[Gɋ'1A%1rK(8)ޚB|.}0$suuB۷:y>ۑ0C kb@K2:h=Ovu^C$"Tbi+S\#) ?\r`KN9S3:)"["X{&Vܷk}ϓ.jD 1M endstream endobj 234 0 obj << /Length1 1422 /Length2 7584 /Length3 0 /Length 8561 /Filter /FlateDecode >> stream xڍwT.P[\VxgEӳ$`[!l,.o Z'FULYqs߈{:#e࿴8;wT i~/=ܼ!J6~ k߯,^ݫkqͿB{!, Z¬~OP`/xejvn7Oq/ZX x 8oY#0 l;3  lU%Cʵ6$q%P)64j#V'#}VDa`j׮.+sqcO.:M:ɻq  (9bEMp)+fϧ5]q,Z:UIE_.k#-uOɟf-;D3KROePhu$\'v$S `Uſ*rI%P$#Qˡ&ˍo< 7fzifCNКQ` M Igya%820Jv>4jc5ӶN]r!~6x$Ւy"0I-'8-HL2:'񱪋js@k|͸qm6 ڜu_ޚ[Rfh$2-/+kKs̶/ آ:D3=Q֪TxX)IJwq:Q"Sb tSxPaS*l Z#MV%a^Zl6Ƒ^pP˃PYqe7NOitא~N >fv/EV;;ba)m%'.ĵKMUV᝴wG* sϭg"ڈ@j=(Q).aT =J4IÇz 3"?qv1`X!0 c}5<|x;On.-}U]!'eZVyW^C@Xf!*E$Ր ReHb|#y[M*c2 wM{CȢ᠓gsQgzgET ۭ;u^; đa^?;tD _6l4ؙ yvC}-,Kw9Vý[Tьn77FO1iI37!m'JA/*Vw:޹n$-÷"Yd k7=~ ׊V+fɘ9u˶Ij7=1ݝY.!&KA1 .[dN~mBR<7pSpuZA`wt zBaq}Nm_O+67Gf.竵qi6컺ܡ&Ѡׄ@W ͓9ʎYfɑGO^e2DMV)y 8-cIX~cQqc 'IW'@*@YSEݟ Iƍ-_[z{V1(fE}FjO)\'(攑Ro&rY۷ ˿0-kӞNGuV/@։Ы/p0<+f^30#[Ǫv9vwísK0"E䣫IiB ?xN=Vîkg*{"qcxZsr:gַ\ D18i`0s2t:ߧ; 4׳t)cz-i={]RD^za&k#CU¾򌆧J*X 4bBm9pbn]:hiJ.K[PU٧4}|pM~A;,NV-`o8w?5UϺ0E>^ >>aR_nD~)=F4e֯˓^q fAӫĝLflgq0B>hPErHˀ[u b =hԒn 6~e'dQ!''-YV<}jJ1u.48b"La9OkQ; _]So֨މN՝3yk|ELb޴M 3llD@;Cc]+m 6 KFF=nbXZڟ-PU >k1doV lȄ82T~aҫbrRj8\s+ή$XG>)CWqW`j;@iY)| yiqe(Vvm_1_ _r9] .HD7o~U&k==~<(\,UWiE&#,e0Qt24v0"9V6h\A@m.T[1kqyG}{ncyN7;t^<xp?mHP|sviT22Y7)]H7t~bO1 gJ<ERIS1tbW?x},g}<3[nrAb,|%bҹxDk m0N(&cU-#|)3ZGebqnћsmD AB¥~X\fDVp\}+\kB ~1qItݚlu[[nG%~hF>|֍v c ha̫Dt=H%`"I!s-M˹̝L0F6YiOg7i2́xeZO*AJ6ܬ/$预8q >' Vk@՛7ڗH`Wy83Bv'ȇUd5Kr<9"=/ ~Kvښgz\~JzKGm-b9k7LK2Ř1N(%UuzVeH(8}Za6ꛔ<2-?R-@-Z=Oz}Aex\aY.Ga+88R[Z1W^S#mgFk*dLe @W_J)5]xzmG.?_#Ef|Eˑ*43 È͆2xIKpΐC|8K*݂?$Y+uXz뷫q͵+ozT|v-MZY> <)M4[of/&m*1lbϮ;lC| T5$OsFN*k]jp&h\kv])TI8 33$}uNײ0Ͻ"Qr/ ^Tf)ltypVI-0?pa3Y{-͇|ggٷ hg^zY]HpmU>lg`Xtx6)4ԛGNKئʐ8V ^CT䓋~1N"b%'a:bBVK Q-(3[E\b\p]h RL'%gz$0&gi@-j?r`%JKQ:.rY&x[|z(lKD{2]40gɥx_VJZ PxTK,Xx]TTkâRҋ¾'(FFV;I$I;/քcA߯eesX@,#qD >ɤ흷/>?3A-fR;̒n|]eL!o`^4ς18>N@?z%t(' ]mdQ;^I~aYmgHRu|xBX0.oD9`k9ӆYl*&;n?4rR({|M:ijs5)Y2PǪA:_+$L))zq ΞX(Ƙ/hSjr REZv~5 d!W_4j~QޢA<ǕCDt +ӪTIȗ\WrL m`K&GFmk=bv<~/_ci_upH9 GL3_N|r۶sD0%%T}s69146ȷ^1qAAaqbNNTvRɦSWVM>X2:Fp,`1cGAe?ůM䰥b)$Sr"lWHZ InͶ(#Tg/f?淫~6.z^㸆.iq:N3 eU(1W{;]YĦ CWe8.aB4HV}́wbڠW Udf6Z}uvB N" F?tw  ppuWd *Fv=jy'mRhˎƋj}|y'r+S7i!^iʓ 3tVugLrZ0fb2I٢Ls<2-eM#I;pO^#;z 5=)+/&f; d"VhWe&BP+qaW:]9b?{do"=d Ax e}r7*DG}!/hӢ ᴈEx6#fٛO^uȑݮD Yzgڷ8 rSmm٨s٧iB5|9xoEoCo]'j^+t'b2+չ)\DUqC['rw ǧ 8EM30Jjy:g|I)i>cߌC/M>Ymh5|F+yo`⢣tT5"(̂2~Pg>Ъ endstream endobj 236 0 obj << /Length1 1415 /Length2 6649 /Length3 0 /Length 7619 /Filter /FlateDecode >> stream xڍTTEi*Mc t&-@@H.HH& EAPA:H]Pz.]E=w{k֟f7? -Dy@@1 YXah8/7!! C"@ Ac|4DT$$@迀H71<f "P! fW $**; u@ 9!m`P?JK8.b||g/^ C;t(k`&g2^B ǯC{Bܠ"P w- 9r" w!~'Cll.7 a-Eu^AB($&!!E3_l`.h/ 5"߯2[V@!4W07 ڽl Devuw3@\ݡ*A0.¿}P4 @]P/_]_n~.Hf#EA<;i@[ ` !qCؘ_ceD/*ןEz|y<` ˜цjw  R4B `7oUb60 a; $FAVj swϨ Q f /PRyAmah?758 F`>., ?b8a> ( 1 (пˆb>6H_  nnoB1 (>^I`f!YX>&|?qwst+e>!Dڈ8 i˹{YO'VӘ885oO:DY:ZMvTOVfʊ9%:\r|=No6(5mnfJDL?D(+g/7x kA ѥ:YԲ hkǷ,=Frkhd:[0Dbt:tng%t?t~xo WR[,Z:ۙ bhn6r f8QPe x2|( O^[Z0{e,w2Hyzeo9[иHSkwEMJԫvmwr1L2 r9!~]y$ȯ.yukȇ&~1V&uޓ!gPқ'}]ފ]fRᎡ'%X3h8G_p$%4)oGp]ך5|7X嬨4>\XLKz?/vps_Vlɚn7t }O /"L%Lt.j8#ԶH8?ovyU[5OҖC4=q_Ƹ`2O汕A4`Eh䖆.S [STCݔ63yoRrߏ _ݿ47~)uyGK]Dp[0Kzɸm;w?l';xLs]]C:TȜ]|0{ѷmL+U?nǛ:W\VgYU-gV;0S1+wI[*9^63=΢'|dVprݢ,t3Ng7LT_me16j)ʮk :1/^F#6C<UlEoof'4aw(hL.'"`I۞M7%{y0S&8f/z_ݺ CyJ_^F ;>߷ ;7k'. O4ѡo,Kan^M\ץߊg}eN}b9rl!EO,bpmJ鑐خu| ԷtzU= fyQ9;:N9;:7Ϻ 5[&٣rxYAqC@lGaiEA;Kf@{wÅR{RS&,Ǣ>Ҳ1|Ԅc^c9_4?'pM]峪1H<5pdwn:8lV٣b6h^a>[4vvcwe7VMjiy7{ 4=Lcj^(՜ycaKoI_dQ \ wS)P_^\K{4}fva A^&KA:L.b9$H? ʯ|[KƦҋ2Y Y vbi>J0HHȹJwưn.^!  %(.&,;QT~^?=uK&^NyB !6fI W'GgH_4'i4px)-m.l9Z^.mUajau[͞D0zdtS^~,l',=wrڨwǕfti-LB27g2_FZ$KE03ES)~(L/6صNqOb/1sxƕ!E(,%}.HSuH(7Ȍ\J|]*@kWhU*4p0]xҬ=tPJcI7S +k#":9NJ _M{{i5*ɱbsDnt?ͶX3}y=TV)3+OiaXժ.X J 'ya@JC_v|O),%}2lyz%?\Ho;zs<{PC&[}pwpt#-nNlpEx]qEjS?,w{) Q..Oɾ@%`耮/ %8K"b*}XFHśr\&KOyuQeǒ뙶q"ǔZ!E /br6H8d"&_0gezJ=py{YI`x[ .-ROu>2^=ٸy}**ٗ;Yd]IWܲ%»J!&?+VjBKMbib%kQ:Ro(̪/^nsWrCj(/B4ttzi 6ߌiȝ:-._T-|4x4&tfd &}LM Q/->bb ϋ J'2:?Ž;4Zbx@rd,KS3;[KzJXyMʭϘ.! YҦ[zЂ?em[-Nsz#z/\5Y8~e&՛o Ͻ8M2NJW:[cswv큒ݔfN@#fV2Nx)/Lqݖ3R.Sk`f'fk_q ޫ|HR}#lEʷ;%{wO_]%cvx[OswomE }c"Izf,KߥN߱@m{eReGA[63E7G %̤n<>~,|ewMQvM'QLkkyI +Yo#vD˜ƕZ&* 5ܳ"0w_@7KvY ^9!JPqJO;Kh뗸CZuT{J| sя5):Ģr,Ϟh#BtLD{u^ +WWgâWNzw Ew5N,ګ?$ӵE`8]s؏QpӚTX|U-{gwh[٣\+[qM6E"#Vȧٞ}P !,x$DCg" ,uأݞ(k& +HipʃaKA55:8\jw`ݬ~w̍ػ!"OߠdBڝ?:۵c!KxDy,xtMm[ՑЫ>/LCiSቅ 3pŽ&w{/ uʦpJߕx)sZbB'FMh[R :Q>fQejG*ƑP.1A7xkLa3Y!Z˶*Im4K ͋3dK2"ziJ-FN6rU5Nhe!TQ.Fd2e;c&1U($26EH,k? c2g t"箌#>1bI ^tZ\Tw= !$ d//a6<u+- m]ENRjZRS-e/^b sM1s7РUf?p6zzH RqxcVhk5F@gESdА.425 k*-S/BTk2#$^omꎚӑ Ƙ!q4hxKf-Npk޼ E븽x3SOՅoN54Zޭm6,oju~ \^}>°Ӯ­N#\6Kgs+Nς endstream endobj 238 0 obj << /Length1 2003 /Length2 15599 /Length3 0 /Length 16834 /Filter /FlateDecode >> stream xڌTm6\mʶmvWmM5Tm7Md&ۜl}x~_Vk]ۮcv9* Pޕ *`bbe`bb%'Wr-%:X9@h!3vwȸY<̜N45:Z]+## 5t:(bKPrK`a |lL.nf@gUi9#/c p{OgcSS;Gc{/+{ -(!J07̍s1urtuap"a>,no&`gwu#?1+gGٽꬍfnVNn@iM>D,v&&&NnV 4d##O%~>@?+s?Xcw o#Xff+haeO1/|g+O.1ϗx9zcgU4d$ib' @`c8?>;iWWe߱>gؙL?~GO #mwBnvV^| ;|6@3+7v5Xa{ Ehdjj״%WclJ.V\+/j|\.# 9}+0vv6hb0!02;~>a('3Q_ `T~L? `4}D1qM>ckF* X>d!>Hۙ}lb}00'_-?rd0Z ~p m/`t&Ŀ9umoU^k~Nk#)M#;~%4►Q+<)㟺4t߸^ |/Ep t zA^U5\(tnΡ,zꇼp(L(ıd7 G0RxY VE$;x9HV&-ٻP=e][J-@x4~!hH$$pBA#Rd8vK34sJ`Nbp_0&gj"vMqHjO;]/tbEKG|KbE80?6P|D^%_#5nҸ|SU{']!!+akǤ~ ^ L৊z3j^W_Ư͘nBu2 LJ (3h]~Uuim FLp|˙SKٵ!O&^cNG) &1 6=DE>#.RMU<8emJQbk9E'd&_U؅Uv&LK4OF'P}y淽YJ,y<Ԫ"r|嘿E 6ly}FH[ % HARAB|TP԰v 5/>:Ϧhl@ڕ?|ȭ57v&Rd>c$Jjd"$M1E_y]|oA- /jihPǃXb6cuI|+Pb8|/6ԝ҈DQέAPSzu}%8-8X&>5'a^ƇB ̱8Xq6ݧq1 猣T0Ҕ~A4q Y+ Rf<]kED@VdP޴k⪘' 9 "|xP3yNکkKekQݝl2SeWQGc6efc m'撱"@YYl=nhBy|loXrgwhyINn2i97DE -{[/8 ņ+>YBXaaĀ|zʥ 婽| YF:ҌI6n(,`TѯVPX/+\ϖ5Wfa,xGI]E$ZSkYo .%؏5~4bB ^ZNGBOTmIX5vD TՖdɆ@*Bax&F\n nwHx/aj6r=R]QpP5%<'l,~imXF"'N)qtF"v_, þY[JϵL dF!b.Z;h,oA\m$buT1(V[ehBM{@q޷~Pr0bn8Qq0|͎>r "iiV{%S/.F;U˚< IEC.IMDB!ka,lepds,h?<NM HsF5{i$Pcka"IДZa^~94Pܙ)r@Ӫ͟:e ii;kዢ#n`'$@Ob.feC~!IPhQ@^t%/}O-|ɵς9Ҧ[1iT뽤rHc7&# M, wt*AGVac&dH@zŸP=%}\ncu?-9,N7+{ 06 t!^pĢD>X :LXp&a.Jfdzw5sr|?Ql}[3i'JC xWD߰ϵCC~:n]5. UhmD  '-䥪)Ad2(9˝)J")~mwnd'[TX.1K=$<:6 Öl.sDڙ)w Lu #F 2O e:DWmDI "2n}t';jj(#;h>c۟'u Y3Zm/%>*ߝWj!(9@s.j Ű)hQᜌlxsjЩ*A/`"ai`b9ňYH{k3@ҡOeǯ]Y EW_xTq( Znyv]ej=+Bĩ$Gx'Z1V>Ŗ &٨Q\d#f;/ʉ2'jqS`.9 FOy3v(1?ñV$/~m &l+19*rj|{W׍6uZfkܾ;)DWL&k;=y$+%?4-i>%|Y Td^϶X"*Yk:y䕴%~Mr/bLXۘ…}*4,&e칚 #<5_S7iRlK\Cw Om>+a4$#m "*Eўn…%Q[m\%Lվs9KmJ\yl2)6y܏u#9dxpD,\ejHKS审Y\ Ty;x,cc4aď2y?WIaɖʑV(E-BU_ Fw_ %VagWң F:hS]A:4-LkX~r'6j} ج%ޫɻU9IʇI=p4>4 Zh]UQAcdCs3+c旱 MϵUb~ܖdOBF3-w'mN¥(Vn=kW3Gbw`́1k"x!Jf" hsL<Ԙ>{J8 zsAԞ_'f#Tڞ}Kl*= bNuh3"GzigsY#Q})yQrﵟ.傭mz/i0_GJLhW;CH`,ô{O_[[ƻKNi=y5WN}zi4dq&ŢV*>pn=$t~v_0)pJ=Px&eJG,\Ue8ن[Z&,sl}mXK$yxkFfEkYzbfIPb?gK42*mBU\5mϤ+r)l%3@&)N{$4$h0]0*% 7 ˜{@-c*u+C\Y9B|F [3 1_)ZH~%QCXjCCpدR x!HfefI'6!J?%t8ޕ_R)YLx=IcXTxʭMPVț]eB1 )$pX.@}ݠhЉ{7%L@QJfUW-}%57~3E%s&(quսTWIf9f"!d°X@b0.RGYcJN g}FqM{(K0óKzo4VB`D<24QZ ϰa_4L~ z$>n`cKaJ#\H/EOhQNsp~¨~q% ZΧޭŃ"hJ{GY sж*]m}0K-˃>fŎӡ VOVDΉ>ޣ~J;gAjE *%Q f[UB )XpիM䮫cam͚hyx )RY&X"G8qr¡4pv]3G~E/P&)Ve=ر]1DK]LQ ߷kQ ?$h_ o  sЭv>6*/c iӐeRЧs^u0w|ɪ܃JŮϦ/ևՀjWm8D ʕ>1gṧiE)B'DG%5',W ݁r|qP^ƴ~R/\5nwW?h4,}@AjFL߬2C p(%{oc=gR;;wq#|}Reqxړks2ã\ _ӐY8*P|΋ @yӍ-8ƨҿ>\`YL+6\\u fMXn,cϚ}azOu9DK$1⡤M6JB}yLv5%Bqv9_[-Iw%O:rY]ލpE2 zxvpM-dE[+ھ1}ZNoہz)qU5|w֟W@yU ܦp|uD#a5”!C (aPP9swZ1}fB8¶)_id:¿,X !|樟/;S<Hj"9mŅߌ`$\HŜz$,Kwe' 4Hg3Q¸Y-`/a~H\p& {CE䞚i=Sv T*líc$6$nm$C l:L^4b}}XH{9\/.ԓ<|C\伊"DxP0mϠT)c` xylyK G;U:)v,-'j>0ҷ(8 nJ)Xh1Bŏ̂,cvRHHX+_oەDZD/8dL#hxnB`pCGMJdm 󚩭#,Rڂ/\tˍO\[ W6<&0*?h+4%p?.}W7߅:L|s" [ 1ZK:|/7⒑]:d W6aPa} U}FiL[;)l+$)HF^ȓ'* 4"/ W4M`N,'ӗ&B@Bqűl[0&Eqk< 좪 ꥛O|`ߧj,Z!{[.^uut7ʍ>qK}Gi^,3՚spèO9NyX+s_s)J٤& 9)'q#MC0CMnXKI©HwFlQKo@ + = =o@;yN@+ ܭ&E[:( RNJ=_'|rui %kV5: \9I ~-]鞯8{=ӽA=lji;: VwaJ1im}z8l|͓)973{[ܼ@]m{'Q$ꂴB>Su˾)jR]Y/:7^#Z!U\pNKV SZۨkɈQןT^&L& ɯ멆mP59\+#qIPb$/q|j?sU*=TrHw2+\q~9L$]NYX ɕZtt`3SŞV_ B.z@;}'1v=6FUV(׵t~h~XvJ};̱%RciF?gr0l-4ZX誈)+em}OV bb,ȠI9< ],e .#xLbJXXfq˗,vuQSgRiL\yD>7~/Ҋ| EQ'_il4(S. %mh%XUPp~:BxrZ -R#X7ؘ`BNVݑWZm!tϮ?!*EKiyE;#maqp/?4&cGda Ū:h> 8;Dп jqۣ^Wh#jdnUy~nNoU<~4%_9w)\6jXc @-b=b +IGw_[ ;Vd饩y͎.}:G>ä]Gz7Tq_c#s +G;s%wV_.]FW7Kks h)[p"ϑZxtZ\TgIÔa~`{l\ j#&Jiw%;jqA? Q+HmŚo6=MB<:i{{h'zaD0 H-X0Xap,ֹ$ X)~F3X e AB&>Τhjk4R!^vM׃Cy( T4KfnaUE6ݮYC gyvPQPo:}CiHE`7IC*+3Y[S + UhoQ㥁<+|Y^Qߵm}P%}gi>? /g 1=눓0>lߨZs'"p_ns8)Q7љX]]|GWzUSPXǩ2uH \l@lM#l}|l[v]rd@fn0K݉KDtmmO 8R=y5Ju+f [w*ͮ`ۢ)x"5&REM9VVbXVͿ{?FT@Ŝ͝'RH>+z+o](nfD]3).J c`W͢Ea]孱zj>Tiy4 &[bԎqH؋7$*Ol(Uܔl)6jKFpE.qU{-a=b %\ԭw*F3}\[d59Uu*h֣U=B cy.lMخ<y` e_sS r/ @zx$^Y̗oekŞX8sJW"z[). EXk6e^mT-Dvcb8!cXy?qY8Wl_}&R|Wiij;tOI0.@)IJU@|l4ereo}IU&r1MZ"|)i6ו9s~*Xk9 FdhX'b (rA Z~= L.H҄^W7Ìw4JU%p1sRš+o)* "`O7Js#C |xҏMn5ӻ+rM|X=&|$o㴝7IηU>W7Nʽ❾t& Q,禒lYNH_O}%~w`ӝͺncwD$٫K\SLs)Dn"Llv3 of?a ɗh<*UPauVh!B& :;lD볻/ CRhm6L vu[CDK5w9$ϐ>{$zjVɑ j 'ʛd*Cī'9b1ݰw߃8no!'[£eHqﯺ+שMh։gk 3dӂrj:Q 59yrO2NW JSPk`&$ mTzAaOՉT >޺Twm $B LPz w{y *S.κエccY|Dd̕2oIS[I?:~S}پ*\Ԍs_N9?$Sőo4PͤYo/hYzF/L) #SYڶ JSئikgKaGVzu#P Ё:~"Gr#S[/HzP:5`s}"Q~&Vi,ۍN"/oPrԌYjvh5]tEӾu,vvp^20je0";ڛE,aI]ك4EulS㗵?Bh[]#XͯbTkzM Â^ӾRS6 *>E{ĆδDbK› bԀ5Ue5H)jR6Iݯ /ˣG۷|Ƌ'?~nS\U,2" _B_Syyv AUPB<"Y*F$H3 @ g@>\6z= %V5 bi9cVp|vh}V?uު]b;:16vH :̏e,ns;Ͼc]ˤ"7:}Z\FΝrİoZԷ on\mlmOeQ麒`_ } z/kG 1 Oa\MqQA`"Yj myQ l9ޮBbNԹӊ-mܗ9mo>%1cl`W9m?\sATPfqtf >XQ3b5`WM+y6?vO~qVNIÝUtEa{R trMT{:NJo&Xm >2#, T8v>I(// :Yu[!)LR&$K g2։jq*1dMJ x5vqQIz  oSz~Hw ==#,H )֮֡Lԑꚬ?) $G.㸢]~Ӡ<:k0g(x&i]&v/ZJj +l*n`"A_Vɔ6b7.cu,@jȫL;C Es6u$4E>WD]:DRZB0}B6ÁZɄ)> WDMD{ճoɕGTE"*-{2X,* nU VL,8 $ ]kioWZYKsqތ=C=bOLXkXqYW`uԆV+sXks> stream xڌPڲ.wwwwN ;5Hpwx={5U0_ R%Uza;#3=3@T^OAfl BdagQG3H&f ȸXY<̜1 G1O?w&..@iDdf@g;'73aK[ ` *ca r2t]>^T33L,F@3 [?Ab4|G w'&L? ()(]u""v/zV6= ;3 w%C鏫Â?vԀRq&v&cgGQopKM6. ہjYyJ;@mpp(Y8M꿗ddV331/h@7wJq[c;0tt4g ZE_029\|v'`-qE .'Qbb0JAF? (q P>?OῈ OeP@T P?S P?Tt:W7{0Y&?6? 'e`f ~8VOP7L@?oş$러̿6sqGt? ?ah T? hVPOmQ _"\mA{=V?9K *kl{\@G+Sdv9(!p&WR9MtWNͿ m?-99m,D6@  4PN33?iAw5#t.ɺNVA= t;.8cGШz@?'@w1Ҽ1oe]PC0 Şf5גc2l2uuVpH/8խ2/жDgxv؃EDpjB޿5 [d(\ 0%VB9d^ʦգtKf)p`Ѡ_͠ND{iolpY^&\]ǕV' 5-cGl=tK&,*Zzn!=C uvbL~ ;wC+Ol |@ЛW_8`9ԯl^n/١GӒI/8NyV <^<[lUbfUp!/e&L ^?̱<`B ?pKEN^RN"tC;DvQ}`sSs-lAboPp>?+J|fVL!Yi:s4cYZQ{ĽKM)Ѧ 3L[bB3RR9XJ/{yspTh _fD: ȗĵ8әZ3c{/=(GiؙlԩE6099a >eALh1^d<4Y9JFJ0+1h:R7\f{ˍpdLMڽpuo##k',O2ς4$qswST7=]BhV刁B;z\꜉Op0D}=Σqo.ZTr[0(:J1>of~Hr~v+$"]5#QĕS#,U;U;$-T1bx€ϙ6ZXF^&޶Uf[ c$x$khI/EKޙ }aEoU#ֳ938?,m4ȍ#&tUضPjAh[(&BG0?sJ '*KHPߐ3*i)}7ƒ3-M A 'Ua?` g}{븖OH`<+Oj^SlcLn e+ۥ{;8/V%JRU,fDZOfgށ[mj'T6;M>1{C j7ϊ7sH1-UeY [z#8j`T$FE!ɞ}82n*Oq{䟽m( :'j9|hv4GQ"qd5#{@0)iYoeu}ͱ&:I?QM4X<3|k,-E"k#PLL[KLC ղU~$hRRt{Pi36ko9?`]5QClӇHJDXՉH#\sp ZlXܩAa*ʦG%ʣbhoUrW(e+Aʐ{XmrWXhi&R@p;X4{Z;3KkNa4y0]y8Ub&V} F5OC!ez)l>u)0~Jb:fXx[h$!Ao! ?q߻*أoj&il桵YJ[* 4l>6QL]qIj,$lZ"1Pa+=oV@hd~G5 ha'%zۢУjgf#3J#v)Eq88Zu5'5k.v}jY1r{̌c"T1egE!gcQm̘:*.T˜e21fGmcb  "t~϶DGc~5mɼF$ :3/L < ;Hg"I}L.- .WTMN!g17< 9ʉ^R!2Un=}[ o}VI3&u^/& ;tBWM+(h^PGL*'U]QtsG$5:q? Dj'ց7^t_]0a0&ee9 oLK g->p0REIH.€6rD Aᅦ!}uIcA[k/%BA u҃IDn"S{qϲy3 [@Hi@3nk>c1huse1j%^0نV%s#x;[m,Q(=-~n3vSM=1*hw5=\8> 71bAI i]$]q#~d>M]Kj,6*|p_zY HM#T(54`Vߐʐ7KS5s= a4vKnJZQi$|I "*ǴüZ^$e%p%^,2|Xp7sM6oM 9nȉkLcWF;eI)1OQX"'?P TmR? [eʅ>$"5t1!?Q]=EqgD (b(X#Y7Xhpk;_hd`.|X2*w c68}ӘJ>A/,CVn11(!x )QLʦ=mwp$x9@RmoDqX~+,5Ğ+dFe8iVj\{fLwXÎN)FaG/Aղ_j +[͞|nV#OPdskMLʃRj ~5Qϴ8#q,_E=] uEtiڂiG Z;BtƇ_aIVcm4}긆)\7 :0my6Yqߗ^%%943h[l y^DQMS"׀ܨ|xC1op4 #|ș6򭟌*OQՈ_y9埼r|?\>Z_Qu,[%6E}1Yײƌr!,ȑDh%6bV"6,TVܹZSmUѓuTa{(<Hnnw1ʌh-dhb<>{E?ܠU|p%a^!)ZQ ZP#%bR|׹=EZZF:^~1n-O+*[O, &dۮ`p P'fvzHq I/dا#ةdfhaCi=J֡c~̝}Hґt WADo9OZ\BVECޑ΄2ܭ V}JE`pwܝo{99,!֖yb9T{ohXB0lnQ8]!U2R4zY0quy. _5vG3"^J;Hs#@a~ ˰)4:vͶ}^\,PԑmoDp,s{,[ˋ8FT}Y`'SUF:`FGHe6}Q>,mޓX<TS ԨTaE+iy{wp=E|zQF·bJ[6k)D/mNETrJL֥MafbI-bC}1,w5fWϘ_ݩmwN:7I{Rc,|lf91Hwe2cc)r XY-bL^/f[(b#j\O|JЄLZWЋ_٩Tӄk87FzpGt95@I(oWIӹBhWF% tg0]#U©Ci&bmDL XyOy-9hV\͘&cЏlI͟ZdዶǃY-i't}X&fOWeT G:m h,Lk*av!YE#'F͢X|UZi k$):)sޕYiԳ} [')E63a\\n>- _DJխg:GתAGŃ 5F6!;AHEb)gV\-ܲ$k~~xmshXsn=M 5Y%/?$%70A߉آAm1Z?ggncjߋAzR $d|gV\K`+d]R|\!09bBϪ^M`hf $7hR;OiRlC8>ݕPi#4sb7ImBJՊ-l<_2m"\Q''C>),.۬qW?4C=Dz< oִB%2~qe c0eMa;ݩщx?9]-;ǵBMɶUtֵi;$$uw!Ҵ/`Za}a8ENDK9^هRȳP¾*=/.~a4G3djn vRV󠹙#Q&baPV+s!Ll/ !^pl@rקg_^e(xSaa!v5 K{f%a8wf _zFL $}aV|'X5DcQ_w94k3fSnnLׁӟ(l]5P9/|nj\Bjk8 <e7ƌ~e3<#֗.oz; M=N ~o%ȣ;qBGgA1is'cI?}|+OUg)G0Vڂ[xJGV)(*ehMe7*ygbėqXǤ{t2C܉+3eMN p$z[tc\$R鲴'1 ?Mα%W35KOCҳ\ɽG-8S\2!N Bb=a#yFx db9M^}ZzVfij}d́B#:W4=e:\Fe%Ʊ bS9ꥉY:迊"Kl1 ?ƏVmڒ'{2^RӢRWГSE9dI)g'=M3?b8^ǩ4]@7)C+LoGX:X򂴴iJaND9"ܣ#XVܯ:B@@iLtn y?bFK\W#%Zr ʛA y4Tߤ˳4*DȊhj9)7?f"{w;E;T3p9xi:&M%UsEr5JBQ%oYB<,|88wbtE? 0Z 26qaf 9\%ehеH /q(B+]=PwE~};J([fA(9Z|-۫-_(oͼ.~Yps(^)*H,̍A ܛxD++%jL/g:/\d7*Db3r[,2D!huyϲ7ayp_\'*Z])PWGjSR笘޵V\ƀ1®QtOm,N+W?wbp@!y9@Z0twfP)Q΅af0AIV[r$l:&;,6ԛT%_a!y$ʴ:;iPz귞}YѹH1"ouH$3R#G bqts{q f/M*|1QbW :&Q(U>{ʩn7 x[wjӣU6fjA4UɂlaoF]#ޚzOTb%\sJ8kwhE"(Vw3#Np2=M~üJe}lAȎ(0aƓsZm򔺋'*{_4A 895fE 6.0*RyXe9tQ@ eiH)2w댷]Ԕ;uE1 ]׻Me/5xN[^StSӸ]#0`o^L|;Pq%2{"'Zv[[6KvxFxM' y`&[7>M:Iixi!%>_@7ޜ[8P)eLb=#ُ1Iė R9Dڑ\bL3ӑ?h$'j[KC*$~Nf2EN tOUSѡTqe]*j^¡&e赝OZlLt9z<1jT('jUKS%[60!. ,2bsY}=iUւpG؀W~dzG>4}tιqC<,KRa}nb?SuRke&ٷPӒJEiZ/_?XKSDH1{#T,D ƃ(?@Ơ`9e{CJ$ks S`7󐷻^@v2PK02 ULRn MVFa'Fj]߇MB͠O@Bå.,=b^ƸW"uL]'=r Arm$rC` Wsu/lZk9}.S 2u彏賂9xX#dȟ9b:Q䆭H`6 ?k3]#_fJ| 48^']`n'Jpib[z }<$ZX3PLf4vAӸ@F81Cv۟ =R{@*&OLU+.Hl3&i0scøsA) 3WiF(VjfuFY dNBa,г@&7ªվmv+354kLnlw5Oػ*Z"hkfG`K/_ lW@zg.!v1,?|l4KOx/[8}*uNeTP$W-$6, 틨TqDEW.o»'I_E"Xjs1Xb2rv56dj!L3`|hiANΛ:_Yy֪KL4iu7}λ8a|& $.h iV?Xh|*:}]>#9|<9qsWKm$ 1E![]&f0Ȫ pb a'%C#~g3hydNW f>+ѐ} vy/X˽ |9LysB/uVB3t8O,ȭZyGw#(a"2HU6)+&@psT1d-۹ĠP -o9SzRi+AU_[DDd#q?Nv~=1/"c Pl]AAG5wF2ňQ ^ Qљ͓G @9Ą4]ۉE jD^B\=խB)ыfL#x׌֬0/J5|F)Q>:v@BF"vϢ 0>^m= /3 -T2 j0xÄ_I80ܓU?61Q`~4rY,( 27%7WSM.OdH,RDJ_lW7US" mg$Ϟ , dSzZ_Bt9+!&фl ^dsbD~F;&oɇ.Ľo*g!Nj2"%ŀօD+G[À_ʉb'$]37 A-Jpxq.E7QP,X=N;× 7;0o뽵E4eD?MCWtZ-O/Kro~XO|Ldz(`GZ;%zBsK)W͓D&.DRùB IaJĬ=~4]l3I.`'rb#N4E-R#ow|#d]oChMY :;O>VPd[ " FO^@!)n}*7.Ҙh[|F֖F6G%]ljIi>mւ2~QկݖF8-k/h)rM˵kd @ttl _ڍ@t4+a@~ ] nF:7O܍ҢnWK^f'o7}{+oϕ4T,˞i'ZC ʧo|Y5Cb"iu|[dM|w0ݦ0FHX"s)%tJi:R*;MiK+#! ]C-bwsZm#I|.Uq{"jZ  '8`HՑYd'3)7vKtapzݕ>F)Wrg&R箨Uh:qon&&>ZsmA  |egAV, ՔT;~_T b+e.y/~p_|>'$%mA)!+J𱸌\x[p;c.S0`aa˂&Gp#br|q&^.UOT=@"GpZ%m=IZ":N]>[Y/Y;Fˣc^`O/D/^4VՇMc FL8ARC`^O_ȩ7z"gi_89rU'՚yRkОeﴡa*o3QON ^d9hd\ef}mn^C(x.ݙ-?p%4:(sUL}v(LO$9B+LZM8 s%('b5pSܚ?>&oheD7 NL<"yrj)Wf:1&UO> 8複Lb݂SّZ6ŭKtT-._j:JB;??_qLY1^>Yo(DJ~{w7ke{w26݋uX3LݥoBAT&Cx^d`{7Vn'?ݺH8GY_Le~g1-ъ³hspȓ|Z')=T# ~N `k3>n<8rV^돺^kdgSIrz|sk_KZY`IoZv6)EU jŽՋ(PmbjWad^"aoR?~NJIG E`َ_Uv1)\$s QhVfDfDe!y"3LKzN!I4ٔf͒xv{K_Ea{ ŧ܂az܅%=69/RÓnr{}ی!CxHZ`P|%+5;u҈[_(d]_nN!p28EV Y=*./8 ڼ18VycR%eR,"ql+q )w,F݈c/ @g8T z@A-?SƠk5+?\_daPjdfԍ`%i A[[zD3O=zK@UfN[nf%:=߽H`PJ*' wp;ܣ42s=as(gʴCW^BBT'dLC"M~ϴ=nkkZg4VWZ̆۽U?kQt)||I('E^$[k{fS%P-峴,u®VӨB+B۽h4;1|)j;7$#*3PrʧiLܼ`mme.r?ڌn7Mo7I$i_ǀBXt8qww [xn~)Eh ug*Lde(lUlF">FEc@o^(o἟M.;tP{grtr ` KS񽳏R=XL"e q@2.2orR,nfʯǀقWG1Am;?1pHzC/D۴hlk؃7HK ђϓyEn=){Rƈ$ 56p/a@ Gc}աLf #Íl;\; /}AMŘE1w ͠VD|#h] vr^{ $d=bwY3Q2Cuk(/| 1e[5f~&q%Ʊ~4+tQ#7xŗ*SfH&?]*_|(8Z|i:zgZ%UpC=Fk!>audԤu7Wbj%'2n·":f;Mb ?pY͡(3瑾ΖUUtW5nO\̫$sĞz:)CJu%bАjfwPNJ'f2gUB-w/}ZDݸcQ+]3 9 &sէ] c+m:=Uq9qհݺBs`%ceC̜R gY'A+Eƀ'/?GRJc+j;k?'][Omh}REawpoį3eIH]#\R⤢C(6FRΰ@d.s; %D[, v&-%eԯ*LƜ #6BuciȐ{uD kz[raٮ:u=_DH"Ko' =Fk%]sF!8U H:J&joTsy3Od`JS]8Ԗ֘\V $6lz}faㅙdĤiBX>m~O؛gc(7?ߴ֡Az=简8J +o2,:K:ԒvZb&f=R}5a |wf16-X]fJ¦IWOPO5Pҹ&mVZ_M l4'(9^BQugYN'hzΔ3 W:ʛm)/1_8cT|2hGGo)|_Q#l?3dm^-1J8ux(VLSeEuJ: 49 ἏAx֯~kTDnsa!B4έU$/.tϔsosdhWcTВ(\wA8 H$ӵP 1rN/B~R ߚNA@;Օn/i,ֳlM>bԈ dU>SR[?-@m@x]9*3ҩtQʼnQ.8 a4&"M 0H|<ǿHқg[B6³4QҌ (Z;DZZ$ M޼/GwKYO<Ll˲4]݁핐Vvʔ;-pb}<db䂆8'EN ajQ &=Z 壏(dk:%zCo{:p^t[Uo%`uQ@g$9c2m{7?# T|X6,V_1m1ǘ*obz©4>KJVhSB-T ?f$UR*i3o?5t89hՀIg))P@7 fA_jN߲w0*)Pt r 'Sx 1A>,azc& IÑx&bmLgd /X]!|h\} 0fL25NxKjh+t^M0 >!D?>ؿ R7;c@Hui61 tm<}*m>G]~zzi&`0XǦ >Z{Eaa[=(5 %\_HCV9+ilM6{{KGdp~r_|s(e&y77EӋ*ygE0ŖMz*K"y$O j$g0[^EmG*ol c1(C.TZj+s4V_TBhDe {,Hr8!:Z$XߚYi+y9 T4@2UۜEAiҟFDޭ;wv Ts.!fSe9Zl0oiK&88[TrEd_i:9@3?nbIZ^BjQ̺H[Θ݇z0E:8xp_pt~XNRF7vBƽ4}=$5r ƮL8kn aܓCt6mf`[Q^ȵakz~sS;֬}+p $ʤލޱX-;w_&ЀO[jƨ0 ׯ/]˂ ǡN;d:v_YC$r3?r:W>V1eYލcr%t# 8*,elYB6ŸB$VfKBT.t;x>¶k ÒT3vHo Y%U#{1zܷKIӁ"$_4Le$7N$g`V'7` 6Tv8rH5 M9|C PꪨAτ π|^Ke+49ze79Ç9 Z.FbqRJ'Zk[M2H&Gd\ .F1^qcxP3a F. \+S l3ߵred2t0q6V0߷WS@ScB4?'n%b^8HtY?n>OD'̐UakE obp (7㑱1 }㊹>)J΀ Œ I Z)hYwT %TLf%c \ˡi=hȗ /ѴiDǞnFƹZ`4)Q,> p)n\_'D+爦j[Z(Ix׸MV~i"&Kf{I)0<0?]9w==U9C#FC2Yu%ryg62FSyj]♸ʻC7dVLP~ /~Uf(,pU-~0^l:53i(dQrb҇dџةi͆t6"B&V|]a/ :1\+ǘGk+K; hrdGl\ Hq}Kxn:jl%I28=P8e :_Q%o:q endstream endobj 242 0 obj << /Length1 1525 /Length2 8140 /Length3 0 /Length 9152 /Filter /FlateDecode >> stream xڍP\[. !8A5݂w w;@.ޙ3_^>[|kWQi[20 +@RYΉNGq-F;9C`PH:A.O2)˓2 Pppp8^ p 8esH e6 vF9x:A]' nve5Ds@fxW!k ݝ dsadC\`g` Welt-k_rM; xAP'W t8@S^ e 88o߁ ? ss Z,!v` ms=@;ٓAqus6w889C~P I=;?)&k C",\P+X^o'dV`;;;/?{[tQr?UsX>X^ 70O#t`@I ? x=_FOAu_ =w߱T`OqCvvgq#(7oB2vv 5bg]] {Ye.=ZgB bnYk^2;sU{,sۧT#0rry?`?٠0'SyKڿE?/8rV?S\?S`@v :>:]ip-.0l83 鸪'ugMcd^ttByXt!s/4ùnkJx[zϝIv;I]~r42V->>:] d=˾o~qW6V;0d.,{م {b/wR!w-WgJs7 -1998-l# F{_>yی+H]E{:G_"ytH6F ՗nW'%e3cpju_a$b95*S*:ANY/既#HO|X;j3d pvad|O16A=h'{+e$t3/q;S\,lfka@38JFo=֑?[h0ܻ(q%rMK;sczc;\=s8Q(GoHK[Tս<]lr%BHYS`nWL1V 7a-Kd7 7dpbBew,!dݚ1I ̹V%$#{ـlFz&p(rC6i醃Ñj?j;<5ғϺ} h,[U_27@,Y@8qZ ڡ<* AV?(:a-~'Q^(+VN 0d.YE>c D)\%lFF;9Z,9$T K[XGG8gI}CǙ`4~FiOM/%\g6Kn2^&y_,nW VtL^ƝwvH#SeW~V&s^տ.hY5򵘊X yr%&Ǹh P@l\ߎ͗ 0Q1YG!J fm -ծ>+ʇ zyR|$ ݋7%#|/v'̕y,"rlňG[,'גPYkBͣmvY-Ʃ+iF~y& = sX şߕk~ 8p:bFabgSoEWkO׆Ec&|9M5eK;Wzpq~Dz>L/'Hwݒoes{ H1KDخ!#I,15ս2/5y*~Q.w? l3 f+Hic/N.kn^!.|eЍШj)X=%i)V)mcPvAhOF|˨P | d\&.}E33/Lyw8QX k(K,袘R,W8Ed֮s02 X?lx+ByElX!k a|"A 7>JV2bB!0vqv!5_Nhu;]JۢٗzY"Ukw ;(-d:2ˑ…!77W1%lRKWOWFQm{d ݽ:Y[B(dJX!uwn+[-GEb, tZפHg-;k5 P#^xeq9zY߲t^Exs_'Afl~rNmv-͌r1VR. :]J eff,cbTK]|Sh%l4wz=ޑHh;tfdqBn92Ln ;a~6+~mYkD2sjg*5{X܂ʩ-tb#c ZEr|kZ(tѴ(ۢ|I-!m%(jBQv1џ r,J6}jc֦1>aZN=kDOQԭj3h>Ĺap^9pL7~P+9iDW;.RMW卵bϤRn>T\ j"^\T:-p :iWZCVTkm`MmBoVx3g [%}Nݹֵ9egGP:[\6 ŸĚʰ{[ڄSYX^џgrkbف\F-̅Beļ M6.޳ Odk!Bkbz!#dh(^Ji%杇۩>p$kU[L W4De~ix9Ow/TZ(Z|p^ij2J'םᾉ2GpdsG$n_R0<ٶ{Z){ܲQTHNn1G+A+ԯKTۣNjV`v)V:إ\vG@ƺd\-.f%EAlNmy֮\ u m~)r Ct1z4OS7nˉ떳 Qp~vD ԙ7@ɄK b=o6'II ַX&QKn@sLsa&c&K}q/Z*u!۔q51Af^Etg+sQr7snZc^6czM+&YBʃ?m4J1@JAKZN&hN^ ژM$[ey|"cm3`}M` H6ߴ^{>lI!}ʷ{lcoDNՄ>~iw׃h  fPfw9yOsu)z6?wf$j^e̯S)΍*#mZ½IT<\%t&fJVhc뚊@iF !>ZÖfQ%Q%_0Zؒg/Wd% y[Yؕu#F(pqnV7ՕNG,Z9jHˉ_h#5rbឧe2}tĩvOYh梔4րKmVCn1>eynxkw/ݤgñnl%x67\ApYp>< WE؏xnܟ_)wf sTw4ɜGkp`ֽ?UmY:,UAz߆[uuik @l-"q6̝B@ȀgKRl^dni^*%?6Pfgdp-CflkƎQLlƭHT]QI41.ҾBɲ\ɬո 5i 6h~G>U=*e[lY URp7*Bt q5qH4-K h9 qL_t> to$ Hfwm5w2) '"Syf}݄&d—(Dk8uQ dhLXw}׊ZtDw^MpEm5^BX>N.Z2dq9e蛳WfDfx~UIH4 Jܸ2IsF~g$~/֪O!c=L-KR:eʾ\0({;+| AAezw̸_e ٿw<Ŷl L/T6=3 ̬܎ФjF )Lg;) dձchI|0l2_/u&9o] HcCjU/$hvhЕ5C.eخVb9Eh2%k6d7 Rwʅe{ f8UZ3?XLӞt8P4g%ձ^DdO ȿ%zɂTKXİF]7P}t9+`e:vhrç}M0Vv܍?} k3oeY -I\1a%! MȚSx#hnȖp;"Ro%">0yZ -1T;R8tq Rkv=8WX۩NM}8>͈GE b2gC<Րzni0\ h ڳ8vʳi[j61r$Q_"lvP,"JbG6hkɔN}vcmvwThԞ>g?$~F$FZN6 i+2*^@@FpzLH|b[%F3% K@ 1,w{+tuBء~=`ciF@}n,b.LHèĒJNlYadG.DIҳS_^P*='cAx0ϔF]NU '3szjs 29|GXCh]]里5g_Mԗ(Z 8Ggah"4sP(Ko,*FۻtB2Fl4gɬ?W1}>ЯY@'q=| 0bF:ֽ깃y+Dx/G*J`sb76u}j`o)^COHEJq }a3[ˏgP$^ӱ@z!9y S1bg$1&h2 }bq&V w_&DЊqטcu Rյ-Oa?pKyԼwҨ;l"nj8 lm<؋`٨)+-G830N)̱[+IZ2\ŘޗbsEoXBoɉ'/rwv:Gu }X |qPFIP9-ȃ1h481U$^-0zG|津sti eqVL= ^E{]W|0MU܀@oz"-=-j-vhi !QMװ'oHNȔ^(91ygzұhJ =jaA-*oC2MUq/ ,kD殬݈;tF3hb60[)앦bn BٔޟTx&MjU,W11'+).ѸD .rDtk(ѯؚɛќ3Og?/[=ȼ0EGQh)#3X 6N绡bwZܯm=}!|ٗ]FМpܤ1n RafaA;^.K+gRGYCf1DӛLzzgz6Y_FF!i6:|كRry+bJ(wsVI<弇2JגsMSùBs$S7wRXL(ITH-0V:d睮VRq__0W[g}/3yU4z"DcM634p=$HYPla]AH)MxD݉+/KX(L7bďEL'ݟq>E* Q'FZSS5xf!"hi=jvMe{v,1Qn0nO\AThJqڿyk-pq`ahd@6%n&Aٻi{hj"MN4ʃ4J%^L2kp6|+)V=aV4w;0=:D`pPUqťew8px`BڻDdLPT /ls3!! ?ĚՉHvDԽGmgOYBųGHBWoo-z~W?{Xd&e|hrDG%6^s+|)A'Ys]~ƫa]xX~ Bp3;Ƿx@CC&K6ûՃGaH+*|GTAZL*$ |IUmj2D\@]ae"\vKvΰ5;H|q6>C91 -h (E|uWX:ck$_H{,R#4u"w !l mΙ_Q_]vlym>,5`tB ʟW.K's*H}ʋz3nO] uYIXE) Yx *˸zLw~MAj)X4h:66%I.jM*W>*Y7Cb8f%F*5Ɲ1WK:$!N_^kT6?!j;?P^axqKQ@>Gw|%=9@y:)D}N;-{:)K^MI*|R6ю WVx, ЄtJڵBD8YlQdyeD6}\pLPYg~s N3Z-+Ht+?s{֚XsB\ըݠ𜳱mʝrITR+4[uqU)CGx;Rarؖg8sTv)fz5UmCj endstream endobj 244 0 obj << /Length1 1477 /Length2 7144 /Length3 0 /Length 8146 /Filter /FlateDecode >> stream xڍwPZ-MJM)! {]ZBI@ "M*]tiRHJG@Qwfޛ̐.gs>n *:"`jHZ,*IA Q!HeG.37 DH/7 b*46Lj@4XR@R DzKU pGP \Ho @(/,%%);C!.P8 <2.h%v.@# s ԃx~pM\?1 ; C >G77XS C  h`!U BD tÀj:BhpqG!_ 8h`{QB(/¿`Yᨌ!(T0(_Y;N(8x "^>0M"@ I)C]7 v1HO,~0(/ c :¡hS Ü؛A>lrD" }fF* RRB1"@Aq Jbb\M(Y)a߿nX[APCݏo//xcj_.^M4;gR hM ;3@ /vnGo ;4RE:.q ^1b1tV0PXDcSXz@'7}bPQ+, cā(/"Xmhoa?o_>q-8,ؿLM w#\F;Td\Z5OLy7Q >VLs0vl&jL6l:K2YmL_?bS ZХW7V-\/;'~]Ue3#'V ^Kh^}7~P<ƕ|-xfϟrx&gM+/ZZy|:8DdxmFgLI\OQ6%Ixҝ7֜l#ԣ+S_] ߯_[ާL(}zBR:~I"&TS=GӾlrlL" (tC=nd߂CiȺ .Hlk0 ل?Gm4#s-f'g_4&{2Bhp<:7;9um "xԵxWuO;iISSjCVw;#[v.Ǚ?TuhqNZ* )g}bjyI\Ll%ۻطeִ"w՘*9=ji73$l,JGő.rR!qSFvBQީϜ8$˧:g8|RfGy"*sE$3YՋi׊M<1+"G!|~^ÑZI U|PMxAdtؼ/+C<$:el~T`W-CNuֽUբL.8>ږ9M6'ۂ@:" ep^Vyp8%}2&ƚg N~2ݫY6ɢ_f#HߣP/z6Y 9$:= a u&`MRgY$nY2z/ǼL9[)dM-]h$YBѫ (bLҙ=]} L[URaVI45U)~>sIhYMwm$/МLw]mYuU֦D'ds{y715ײaRZ}m]z& 7xXQMgSotp}#/+X_YD*6`+32јL- #=1F5:?wQ)U~kڢ*N,S7jz8r{0K<ܦ;bB^d G4UGwpIcl;u}O.s4Aھ b8G֊YYfRhzG4h7s[W1SgR>ח.qdZ="Ҹ<݁J,N_W}7Ӛ)sV<{*NsZwήO=i6~uP÷jzTQQVLih㡠~2.Z B\уs\O {Saz{fٻ)BEjZk,Cr kǹ{Oَ.>6UrY9ԡ6|冀|Lm3|.3ud^z 8XCo-.-ea:t3ʜw3ڵ/IZn }ޏUC֕g:c<~@zYp3I*' M+ǗYd˚BE͑ q|J[2_RQiP:Ull{ UݰPLS >~$n`Gg.76*FP\|߫2 =f_H6b9Q5PBicoYUF$ǀkaoճ[l"mJ;ٍ+v}!?Tǡ4pyXb᳇춟xcWu:C:V"36Ŋ 4r ߨޯ2k%_!\E`js@B{;K܍}:y]02ovlJN,7,GtƄrt&9ݽ?t:(PD6UI[5Q_t/U ۷aD釯ɆDYt%|k;n8f=al2.FuߤcO6JX×}j#z.UXi孁ܝw$˳)* }U.N+s>iCFATtMUOސL`Gd80ܨ+|Tz%q7l1g;ܭ3{f`S-)5j%_nXzxeA~iy+/**skʟWrb q>e]pk:z|_K>Tu ^ke>4ھ5c3PTQAIȕhStzhY㫉2X7~*C`^m[sI+\Onw3l) ]!#~Xud-YsD$عXaZO*I#Ҥ\388Bc`B"#o1OXL>aw0 G2/ORl$kӖ/SZ)d$b7!79_ u5V+2A4:xqK)_,Xr=Ez~1w|Ϡb%B/&.jzT&Xa.YO?m{6hIH8`ugdh|V '`ҫm }Τ)(P Ṋ"UKo?}'.ȇR* |/xQ9j&9nk ׵o;F=#!ѳ,圐Bx/aʺw}("/0esRX%2|S<Ҩ 9cfI|Gs6mMQ!!W&<GxwE) Q}q]BlKꜛZS]Gci5rYf riοl>MI1uYՐ*|1]Q pv ܮFqfvl]ܗ-7v8o]Bi;()^gG]4Ezυw`2m9RP n^XZiVठU+&Ӟ7oq̓~jTLl4!Y~ b8 qDAb5ma'jBFPgǝDA@*^FgoTBB٘HdfCJG'hD׸59wĮxJY:;Id=pˤcߝFϓ,o*dU3 6 iM]L%EhgK ą\vxpZP{4GZLzH4V +a (E7ڵ P4'kښJZ(et^|qW$׶UIEv8tk8l|0Y^I>&"~ș(1xQK` cR&O(/[[BanU*[RXW 1׏7##U{8 Kj(p%,+:m339STY2a9yOUڻM#{C;oجOvSB@.Go2WwOHE[3?Rl}֙~ȉCUܢ]70^)oOs5Nz'_r,հ5SyʱV/MEƧܹy(X5nb $yT lAuXw//+on<-PWGk6A J=_0BDw/l111,e2 oj>%6f;Yf QU]1}`INqO E9t\%ZJWhH Y1ꄆM+0ۉ L~G^'d,@szt<2!GJ;\OR|t{:{B4)H&˔QϠ30UN{*y9A l#X#A\Թ(6s~ḱ:?OI5O)w/P4~bU+T1Z۱;!!x,y]/ ,C”_LTY(2"+OjxnG.O< pjwBU kHRę̆IȎ1.'$]h\&nr`pSMت{^{x.^ĝ@pptOy\PKsJ]O+f]ݤR2)\' ZoǶ?p8;t.Ǣ, !1׽ABؓL|JuDM>iZLs[@lϪS3~I_v%4 3#ЉqHٔO$4V=w@`f#TyԂKRe+dS/Jj. 7I_QKY^h\ -_x%ycYwK3Oi^,2B{igY4stby<^fRI[GWN{?Yɿz:A[Eʫ 5ۧsa2_q8.tw |<q}l p& o` W|TKUx sjIP5Af:K2|% K<Iӳ2 ="q2nБ: }QBVu:j刄;wn݊ռUth\ZDx?_%[J;fu1(xP|.}W׺fzuLJ􃒷"tRO+v^a endstream endobj 246 0 obj << /Length1 1477 /Length2 7141 /Length3 0 /Length 8138 /Filter /FlateDecode >> stream xڍtTk/]҂Ԁt"" L0ttw !-"tuߎggfe㕱[0$/O@  O@@U 3_z9-(3 8 "@Qq q+P@rpG?G'(&& !V0Ehe ǿBp lae:Z<0[ h)!ݑ< /C 3ojXX ~'nPX:g+ W#+P(t&<B:n0?g0W .Oa`'_(  'ʎWp}Goo#`*-\A$@5 قaDG ?2;XE< @)[pPR]*YY;WPX>m+ |U`6p؟dQ]>_ w,M8 ?7B}4c(w>.o-/!Q|uAGMMo 520[ߏvVH+?T?5`0 wZ(^PSeZ(>VPC+`Vp_%(,@ ,<P-FI/ j A (< A('?%?C EAwA Qa3"FP@?_>( [WAV.jU߻rYNí$^Wj>u]`]5hq M|8IHeUXz[C-nHcNӥyzQo25tN mN.ܺkKu6*E\F=4 (d}m5E͌";p;y|2A3r˨MhI0|s\_йƈlpKv+YތWI"b0eehlqxk!sPcRDD.6*Cq.mtъjADͻmjR[E$6>jgW kyU\Uv=GTfR˞oicf "/>ͯxFw(JL+mS_ -vce wU=̜vqE#frw19tW=xڝ9#$VhIm>QladՌjxny8CeԙԞ`kDde?h<߷ $:~ a|fHMDzYªy:}gh)s.*6IGs`@$KѵI3C}7=Do:))k[TrcŒj8R=^y'Nq 󂒕e+uV ~`%MH˝5xG!M95*ڃ"Wa@J$7VhYM)6ځ6CBU>aE[mv:yD)h|~Fz?6&j=/}24%IfNfJϲ{(]}ɷw( \^ާAcP)õo^ӄ7p)];f{ߣSqur'R;5o}l]'E_iˡmh ߓ\,Wj5<݁a536vvck<$ԌF*S`x}ӓ{OѶ:[-/ jY\qtK)f OI^.VI@gSk\:A#VOmVxUYtO]٣$q܁޳cxJ [S{(檧)AyIKĸyx-5==ɚٙ}Zo/xsǵE;r>:UPɦȸsI|&ΤV x&kɒ̡#%M8#$479 Rhm?qf4w"k2g`c`'A:Tav9υu߼:]N#dZEdV_\MK*+'+:wG]BWKk cA' qj<4)c[*BIÎ-z*'}-tSuV r.c xczckDظK?i`&:(_tڈ^~zO qޗ׺DHjr} bP~}:L*]5KGgMfE}|GBL͍kcDȠh<KJcaYRιrDˬP5J>,% 12}ȝ% h=>hG PO B6 (`zK?d$Wu #N vO󭰋|"=ȉl ^D¬ -(3:Ks't2ez.4G܄ w:2{SSϓ~|qh~꧗7p"༏>T0|؁NXG*u)Fx-k}b Ry{=SJO]EA~tp)$䧞f"y~%;t5 B_uͬ%~۝?-sXHa.*HjDM+U#(9!z ZF۽WXkL|wZ|j˗TN/0u/$[>Z4$q?V%r^} 'QGN gydXv#;{wQY38O_8cnH؇/xTe5] g ZFlTή9R5ҩ7W(uKGҪ7@]uoԣai?{;aSLrA1պ  ۟k4tn6f07 J *ɑ DUćqpnB!x&q/%wj6H-hmW}2MgÂʙ:.ӟ UOӨh#v )}U蒞$U_'eCX~ry{[##xBFi )j'7v;*ӴoiaAj X!=Lr8pT‘h^:ZNX»_Ek,MR p fܝ}0|F|т-^n:eXEiՀh1&I˅2*0uvzUPbv.:(>;(;Bxrʘ#'vp;皃.+INb%KEi7,8t6k{ӻh~BMoJG`UM}=ki`gsab^{cqZȧ}Bl-J_*GW\Y4n<*N>bfcB*';bct_#BY)AL݈{ޙmrMO?p̦b~N2)v 8MQ76ARdnɾ #< GoEomg:),L{AT:nD.<%ן^BGaDcX Cͻ [gZf6 ;y V@7=׀caTt'{8:̓k_X ߄GD7fPo4x1JPۿ{!i\ʕ5>SqDLL21zWNh,'8eeugE 0IdSCFeSN^trp@TZյޢ۝~[;Id]2?{ :?C|vfcO*f^\RD4[k2V =hbI8[|;8qsuW5ÁerAG*I tKH9:(Y2EC "-NȒݯW'IJ׾j{2[golZb1„#쐹ye!N zT27vy=bI>1\nJ/1SN ?xr2 }]‹< n$S I>kYʳ#M/N;5ʮWwN/vt0*M7v(l;ѤJEƿ߶ Fb_e HV6a}MLB:cC N6^ZZ I4\s9Yg7h;*Jg)t*z=B,m-sWAgQ& ԸUob*i gZ5)`i\׀͆Mfu~jmZfM{vHSW;/"rD bNR@170Zo6s&m.tAMU;7%BǍ?&'v ǞA JbSd߸ ݱ4Y]ӤoE2 ^-e譬W|nrHa3ddİy@frąqGxg/Bq"kmߘE|;G& g.P(U =Paͤ (?ap&D!CCQͨ4A  vI㲺=OZ= -ǯ{~QGhwsDaY.$`Yj.c*}Yҕ{qa BshgB¹p(np aMig,nktJ֨[DT$V:9l)4A`)> stream xڍxT>R H%%00! %! !% %*7{}k֚g?{~YƬoħwaH>A~@IB@!<66c c3{" p0>>~,/t`Oo#W]{w._# @P C\``Ojw6@ p W 췳=wA`' SG"y0_D{(@PߩT ԇyB<~F_aPǬsTaHޯ!`4 r~!`<k( c`$@()&&*?}A.606Q5x=N2A'0/a  =Ai OP!`g Q05_%%?A_O(9aPX@Iࡅ>ϟeTT$|b@@\\8?y +]9 p.?cQ8-t+(z?O忢BTvο@) 8j`M55:`G[5iP9'( T!`G}jM~_7 /j@n[o5CW;6!Q1ר( @5`bH Uc @!= ;!/\oHR?B5A^i$T_ `/8IG츪SZ]KE?pQ~hXC=T"zj.jm^JzMCp[g0#yBiq%%Gux7]퇒w@1s&2Q!k3rŠ82Xd1$R#߆eRǏ i֊Dѐk2珤 PiF+^(UdДG`؉)hOjrU <Y95&@@ݒ[Ub8VZЋIjZ3/+F_jNn'iqrK^@stQ*[_'s=w~ mkGt:X"eg-$EɳE*'7BBjZ+xT4C{^4pfL 9*ONK[g?Ȃ2 &A7t|ɨf"'Jte (-YĉvG8MP25]BA+,G56!՟+ݣ7C"*5%yc!ɭ-rL:{K֠r! ZԸ{͢&_z@p]o$X@& Ovfxjxg5Jhs@)g7uoF}1EiއqwDU=i}o9S\ƉmxFТm'U?~Shf)bҏn|W$:v-P3^ r'CX'{Y aUrnR8mYǟ~9aM<*uVI=K=^xӖsGnqJ@2-?+nd€ĬBkɡka?./`ܫ/Peca|0yi'ǃIU,0߁aBxX1_IJ̓/mh3w];+J$k8L!# 矋}6޳_m|;9~.k}Ǜ$allDyD2K/鋌 J/ ܪF]?TTj/֘ŽN޷03e󏜡|պ`^L[#uǜo~!B4ZU+YǞz30qؽbi 'Zs]۲9Rc+ Ncii< \%4:-0sefŇg K\{ OHzSW 5Owm!7'R>0!_1y뛨iӔI#@ 93=zX;/eIA[x < uoe]DIsg6=]'P-je" Y}.4݄sG1F̰'{ !e݊'*Em)2xU;| _9t7պv&l.Y/|*{uFSeQ{qИ[|=  ,N} Ygʺ8.byJpIcEl~V ӵmZdޅ~- ȩ{-qYgO= >ga:Sxi:{NoKuJvV$OfgVR|0 Ke~ދ/ܔ7CNfNp*iG&[k3֋snڱ-T1w0 NۊU<ճUV-SKzZ/X!>'(/ "$ܛEc R-ɗVr|uwӣN@;`@fq\+Yeypap]`2qr~-iӆIhvRiuKXY!X+ 6QwYME_MYڵƣy:-dr*Ό #]vN ˯Gv۟&qԥ_>_PgpLoZoW h4ʡ!{ΪZ>S]yԔVoi+ L{xb EւKCne ư^lΉ1ʴ6' awDP*s7kY q±BCIuܜ^BOCtfV+tNIHx3Dg5_ȔWfN̯!-Wl\ Ayqab2"MfUn.H?#(ZtBElLZ[QG-ƺ'H95좚̂>p#|CltIN38^"*zaVs fENqO6|Bq, ۀVVЧw^yqAg7}7seފ n9!Xvy$WCu[Jd!Do4@*nYJO\6[IQE'y-Gī#R<"&eu%ᎮˈyBaYt_2<*'X8َ ֧ bh |!oO(qyleyq ;fV&*s'\?a}뜮,aQ(\Z Y"][7=/X;U½zX[xLYoVƒ$) Jtr o0lbXǗ:tU =$>@TYNhVj K"gh[6zOuLU)?y4$e2*^'υ1U? ]+K{Y? YRhǻ'YR4p-E(Voﳅ`YV#j%TH66ck}(6Iλ2bg4c\uLݭg J8+=UH^8`<֊p7Gz'Nia'<pVid?l#Wۗ};a2r 1*L% gU޳48}^tB!Je%.;A0KJXt`&Q?+ZcCq8=E kjV_ wV 롟-+cG cd˶?/Գ[?G2dS.ݪw?DŸ|JYZM-0|ݵPyd|cl7Ru/̅QGF9ۨX+ZM.lpgW<=qoʮ:=a86s=:Z/Br?&SI TR(UѪb%k^W0p7&Dѯo2OSy}pe?\0,כ^ᔃhd8S[*odT1R]ƫDgLSoLkSqL%!{cC w "VKAu}$_Ie0ISV=VFh#Z s.iq]fP>1j{3/1 &l"п_t2 ߢ=hV"M4 S^-NymVOO> Le2(feRJfi߱%Q{Jř6h~ki9pgzPjɫ JK{l$<r\XE%zi~EM]g?U+Ƈ7ĪS(Z䤢C4o۞ 2o N*Ђǵ<fuJ(1Zr6M H/{0‘%0> ҄~b_@60MܓOJMIaM;B' R3Мؙ]* xi)HAA n!}a:mSr_yJ[ <.h q? fC^D>#l$org{|U~Ә\4G:m Oqsr`"xq> stream xڍuT6-Ni=FZBzm 4 Ht4(!!Jw<9{vu羮8Y *P($VP$, Tջo!  89Xg_3 PHPE!XM PH3PD (")+"%+, A<0B1NU7aŕ# TvP:]pg}z#*+$ `@(u1p50g2hGa=!h8gpF@H . Z@}W8X@n" +;\\!Hohpꂰ^X  8cPx ~wU6BpE#\kD_ip\\H,?5]П:!QH߿;fk R ñ@ aIIq :Jo eMrᆀ#/bp "!X-'; s-q G/  [hi>WPL((#!JIۆbv(̟nq=8xuc-[ KCq_"Tc,/wCwݝy~7#;'=NVCW Ai#8HX X3 7@a-(au½?08^vqg]u$3Q I xqtW'H7B $ fڡЀ_k 9 q HuGq2\kCS(\㛰 e&Oo$_,$\/|tdhVnAcʱ`au# Ns72 A42x/?ξJ(,ffKa}]R8T}%k1o]BG^$1Fp\J.OԒ~r{^5Ŕ)n.pC"ob?Y%E_;91%v6q6]`u'c1e\ioZʝn16jdT:ύ6ɂ};&=Er $'8{K1rd3YT`mqGw}2UAs$ I=c7O G>_r58%X6wK8$v)Ko ~xbOK5o&DȂpL,e"m<`m鰃6xEA:k"WϺˣe)bp ͝XG;l>r*\d>PD+mbZ(C|2<M7LXC4.1k*σxj h(' IRC Ґ-&ZÏQ SDgn n<;^p |,-lQ=XN=Ĺ3EX|?S̭iA m/Ffm#`*eFRWMEЪCN1s:;l=YV2CgFO,_,A蛎Z(g)i}!O;]>f,җDIwzc6GzGH ݸ!`v/tTc*$W3eJR&Q/C~f5v Gc~Lۿ)i@U30" w>Dɡ_<93,0D_y~çԸcU>ϛZe2OМЍòy%O:]PXfP_|K^m}fcĘXv5mםψ ~#CꪣF!KnIئIeﱇ6LP4 /%3^WYmO\fSDD+a&Y۾/j/^Opq` };9̸XI `9#W^|I ecWJih/ȭ|F T[AXJ6E ^F;7^C*u{ة߲(PYco1q$xi}i>"0l6W7?"_!BCn@^Jp5^d9dPmLHs*]5:) HȻloҝmiYXo= 9%ϵ0L.]ƭ:a$<,=v49;M뛮G%Bͬ F.<*ϵpz(ܬS8}]GYNRUMP>=i]k>C7Nj*~ ;KxAc'oItq7}hx㦣U糔χᷖ![*)*E62^Ee/Re/F+[e5F{TL+Q@NuXSJ"3sGtZtu.rT=5B#֡igE{xV7 Hlie)#.<[oRϬYˬ&kQm*Y(8BQEtHZ}VQ u~N vZ%FT*){Ҁz(!b>l9"0Ʃ d(u>'n}X*ܳ+ۚ篌OF6"ob^&&kӚϛn|+T?m_]K,@8>8 Yri}, nxfڬTAuwZNR#VQka.4&* rȩh/g|j4[3 fU=DӥyUhRicu'{_" Tj\ӑV_ }*lPCu#&_GJGɍlrMpx}RrQlka$s-x^,+#bTs ["WGOI p%0(m|-9iqTϒ(IuG}ļPJMGѶ22pPqGj&#p'M5ـO:ķ%uS) sT|z9t^kc30\LvlBJrM̪Tjj3U]o _xp4,v &hZ 3Z!ByB}Li̐4ZEXece*qrTY; W"!ӆtq#[*9f{t9Ɇ/N\IH4bgP\CyļvTVO `ξ0|BIChoCWRs4JX_g(X \'RTF ;VY9eS1^2 .Ѡq2a7R'6(? @?'|V+ݿ^]DZQg%:)ny[PF.%vȑIRok!j3TOVN(38ׁR@9[E4 !iƐԽ#&t6̵$& J#RNh  ^PH~Sv8'#-ncWqt~KYQ󾇈i9R10_p㫵ܗ.0f6&d' Ҥ+BEtTXVf !JG|>ySJ[ -͸Ijo~V2B[Ȋ m7U?ZHXu=@!%o'&*skt50Ep>t}T!YDv>/~ αTL`w y'GKH=։}g瞄fp*4^Dʝj&'cO Nަ}fOE"cB[pB˯Q?NEww;ϙ'ewH)7T\f%n JK1*ϸt Y.}N~ ~mYQ| Lh>*}uP/clb7lo?YnŨ4X >N\kh^!CKUTW Vσ=֫OUJSF_0,V4{`Q Ǐ*72KUUXǠi А) #P+:jRZ{HTsSg?6t@[š$F1_$ʕ,6b?v)'.e1d&ү@>$GiVA욍gq!{>qTcyϒM/VN]?X'FA(!cԵHßgp0ӇiNƪm^:r׏ Р h$jrVgㅎ& yJFle-N [ڇzfKv~e_iuRݜ$0 Xve&^;RNƁ|@Zc9j=tEYQasЉ̚v~Ĩv!> CFo *?})GF=5By`˒*C[w1XARߛdeOqi0ݝRvFkMu3yQT\6윢BiK'C+iG]dWlT{mٱɄ^+rsñb]-i1Rb0'nq;ՄIN2lLRCe81ad3;% ?0NPۯdMs?ZhaKyo AITKkYzHW?J H( O+G )vA:e}5 6%AkiQ7.I#*xImMUtXmO+/>g&l6n߹$}Dd0vVq/RyʷMY}Sy[iUeVӎG)MCT-~z[,yMb= zcr[;u+Ă6Y1{^[:Yk29oQ<2mb5>Uo,_ ڳ!",Ex_ ۰گ;rd)K=`"ŹZo "Hڟ`]޴wִ̘ztI_~̑Tyzӎ`7r]gvU56UU͓`,u0l (9 \ZRqct sv1t]3&ݠ@d'awG4u)܋H·3}xaQ>T^^Ě;hcʘMgK.]}~_ #}m P^b=sWvvH|wK .u<ߒ]BL .?)!s+`3ϺBcqgy h@Yexو"#N qgF< XkͻD–q eZytֲ1 gTZgH %?fz7PLߜ{SPp eP&`X&iP^6+s ]e-%sPFk+cRV{Z־ﵺY*ɱOB2 FȻ'f:泆yjzMfFUuK;‡'[vsr ،a7oǾD[tAI=~_b[VC+݃UӢ JH F}9OW֔qUˈ!L rv~szzI> stream xڍtT6ҝC7C7Ht(  1̐R " -twI"t}߷Y7g}>y+> "x% Zj~~A>~~+ǏjC`PP[#|ֈ PtD$D% ~~0 PApV?K-'@@\\O:@`ׇm]0[%87 ۛpxC=0m {4>V#W@f.[0 {vi5>'f @0&Za^k֭ nqC3y8f% Eq~>/u¼!P;cy wOߘο}`@_ $>~fxs?؃pí'8# "6``?O`P\1PT]C^|x+(  @BчEѱUpN78'?ki pfoIw'#eO?qG7⁹ho1/j UCX?Ah^!>~2lA:Śu`p!b"u~xE?h?U~ $,yK\Av`?d0C a=Ŋ *]Yb,1/ww@lѐǃ:0?OřJ9U5_Tx~ ==>2T Q<̏osJ *w6!wXO mF'څkzk=97{MrR~Vbk(?踏^e46RLL%E>qT HnW2ezHxwNM$sG͏Nj q$fuGIs ,dfCj*jOj*| $WbTB?Aaβ2iel9l剟a|DUIԬB :C1q-tAzHb1f],CU]ч!F"c{*\k`3;8 TGew86Ty=KU5oqeV]diM9[jɸiUNbhb?y۸A;i~V#'>Kցq}8aհ}b4nYX{-O܇/kD:Wd۪KkNYRjN 5L,O^e6MEZB:* (RY\<4j@\_݌Nq#i۷*-bL{> ꠦG*x%?7_N1i0/\eʹkZ,B%V $%2=mEe v7-v43.f5"<S+oK` }l0E5[ iMǏt R-y ӃھR`q Ѻ>LRV?F[-D*~wœL|)BԮ"iCxߟ/E|/jNY8OҝKz56/)_]PYuW.9' ;`0J;!RfQ+1cPRaO5/_հ +ei; SwF(&z-vq"TE;4$u)HTܑ9'&`l,:L5YOV0o1@6ubt 3|ƧF9 B8rٍ̮dhͼ$ߴX怫Uhʐۂ-kL~qFBdECLu__\@%L Y'ÉjoDD%d =AHDqZ{?DTZٝ363ħ \%,]E2 oI5J:mq_5²cJ8},H&v,]$wTq8 H&X.I)d\ylu (R[01p\/&ȖV,^ː"ar!zaZL ڋw¼"7_u>^6#C Mm\U dQ@W۰䟌$WxϚh`yxHG֛tAi-@ys_M&.GWʣs.Seno*A%t''~dh6igQ_Mj g&Ypո~" ݁Stt[¬2đ 4C1 ^5l_i j Ks1ܼz[uJ':'ƎHs#-~ʄdjsm~5?k3)(UzH R ]0.7iԭMMլ#c-wr=ZB!4b U;YU;u˒?-"qj,tWv 9:$($2t.6ͨ}E8v4b)4p(ܝE;ݷ Zs2;w(ǜȎ"6YgZM@/ҿ@ e_-6rL&R>DXGUXv}άk MMYn̉c\tIPT" *8N wKkOUL=BXfr57{.H[Ē%v ؙli#Ŝi.\~Ut%.Jst̥נUS8.f 7sk2y'!d3!Ţ0ѵRHB~<ԋnR[# _zuo9XA^h2_hL8#sN,B4 7/ת[Hm%o6РM!InoBB^Be5vGH#,u#tF txG\xMKWBgyl}YKΩAz~R3U.ԻKKFX򒝉$Vc`wLQZŶ]9A=C n 2{{"ݐ0+t4&RMY0:;v 1I^uuqa(Xu~j  LrE=W~p>lڡQ0}{wSb6S#5 }%Gs ߛXt+XS r*k">B]vN;8޼Tbx}&MtE3J:b dG`N lz sbRhֲMU,3gqa-̈^EHoE>)2~8hIOŖ8S5Ȗ8> f ~Zjh3{$B˒65?=;JS_pWΨ^FY1dHCU*v.JunqVzf򢙡M[%`rΚQVQa?O޻sU׎]CEgk'reT>PഖU;H%V1,d Kb<5nq/ n qOELO^<:p))u ZhCm.XĊ Y?{/[kƠ>2vjض[`_Ř&0y7ۜ>~1UZVyc1cNG"ps)O2tඈk>^H4z:Hug═-QRZgz dhoGelō!T۹pR>%ldŘ!>V=kEU꿵ٻNvjܥFnB8):fԲ]oeI郧jof=% };8lŽ { @R c[HzdpU2b_̒&ap?zdRZi(9*Y4f1\t\+^a/Ay|:ifGEȃ=>(C5LAW8Xqo9@hdIupu|ޅ c_s{U[ Im|_U$t23'=cd(q,.y2x+G\tɪTQ䔂ͬ{]}7C)cvX&WęfvYINA>K[vR+YƓ W=Re5a7ٓ@aq9ETnNd4g19J|K(QBڏK=7|~nR ^v'MTL\,enRG{?f?I:q {z,UH2a8 ]}MEٱNx t1̵}*iOCx&Ȳm[S@(g@;2GwRBVU:b J희/ͮMϸ!fB1yAH9xq{3yMo*؞ʻwU^{9Xsdt9iuQAH,R&}͎ O+Ʃ3k0&"$EΩ$Pw4e8Ek,h}^MȆT}Hz.zDn+#mjR5J"O޹$Iist [z;6z+GSl'SlmӨ>Ϥij#yձA^(zQ@kJW9~j㹤;E@ē9)7ζv BSٸW!lҍq4$Ӫ0K&dP}j/jȟOIVEo>j_99-H g%d ̝8({^'6`pbrvrۄ=uS}b. ʓ/fN_CxhK;T}@CJW.Z̬ٛBh\wGǜJ K_G`Ԉ'6Qإfo1 'Ӟv:D{eCK|ֿ^s(0έ +tbg`(P;j0ӹa|$pV.!ך'$|t-ե @G K !UxZww}bfT8 ચNUIPCMk=5*HdU'w[mΠ@au/Q*ɋh&ۓ{E*ƹ*T+~Q #@$R', xQjGdFX 5|0YH M?z*iT4)Y̺.K5ͻu~?[CIt_&FM=դY{Z$Qf~mxe-W8G5ƷjB[{$ 8?ɌkkvYL.pER7hcM㤇JSlKNuJnpLt2s/[~>Mvs$6jebȊv))gp.B.:j'g·t'qew**6ET1,u~y/*g˩Q+SKRC {,*K#sb4 & E_ 6Ћ_sLf gތ/%E,sV8c^ff r_/8~un\NSׇ&Y{b0w!lV3 ^nªb|ނ9zd T Qs Etfax6!祾IR{gqr∉>=ŘGYY|efh]vIb ^uC#I5T#I=%Jo ފ zlK\3P)wP0DQiN\#-"u[;fm*EJ _hw Vawja:穜v$kX$q\;[MPrzEp^("fKOZ)so{6Ha }|oj,C>2NIeDa:="g=Z=Yؠ"Haf׊-so?9Aj:P [UlQE[܋g3ջDx-Cl|D9iv?-$j55L^PA8h0J]*sw?ogUE]2!rH:gQxDo=#]K&}44ܟwPr nU6zq!m`A,q d`2ـ-@p0g(Z!zC`UFS&Ҳpt*p͠\iE0E*D'T{`P)ST?&߉FIvuUU"=ю~8IQ ('͊dgIVT2h4ʝ뭈O2g>8.^vU wk&w<;tI"@b"Ɗl=MX7l<:PBuNVNGCS,$pʻ]Ğly)G8ɴSwڮt]'UT#i;A>Ts{Ae^WԘz7]\`9̑8b'֔X:->^g+WKAE(/ġ˱E\Ca2AϬ Ɯzg p%&eCMzkorч3,}ѯ_vHu;ؘX;܏ȃkw.) ȡ])}7OZN6%G|҉N(!%5.=/IJJ. ˼߼i7>3ƚ+CUn0|Sp"F4 #Lb~xw~/B0XlP)II԰.ok񸴺s-y{? G]t _9wkK^K?–ODloPF|^M\r38p#T~2ߨ*mJ|~S6JJ9ۅ6\w:5덁u*yXw endstream endobj 254 0 obj << /Length1 1683 /Length2 10470 /Length3 0 /Length 11551 /Filter /FlateDecode >> stream xڍP.\NŝABpwhq"{Тn9{3NfY7 5:)P&x!`cdac@9#Q::x4q~I8*ڃr.vN;;oC{G+C<AV/y~ЙypAf&`%-@ ttBVVV777;'{GKz& t:[(jarSnoflAf@Ӌ xPU(C?4`u8vw g33{; Xle)gwg& MRbqvbqwc~'r_õۻF 6] ` PV/?2K3tͬX'P,^,/H^N&@ ߊFHs3h #E c{;?O/ 3zcLjYtuj?Jqq{w3' fw_u+ Y9]_kAK@?Dgf3{yc.,JH=ݟ/8l.T *A.vu6y1 ٹXظ@@s՟S{lA` ?%3yE^ CWlfo{8y&&Hl/xl92XY/.}H`-qXeA/X* ?`51K5\VAn+_%ͿKZ K"K"DD/y˵ʼo͐[~V1qp]_!jH~W |'3/bAcf/Gs6wjbm 6ݑ Ǟ|{1'Am4=>lƁMCm)m1 XT>>NV b3mTNoNI~spo-2A6SQ!W")]<i.7ZLFԅbX̛|wd?Bd8#' Z6y5F_ bE_=H~xnyL~ >5h)Af!X45UqMt~v`&F\euv!_7\uW+22}~\ #DME\yyH]v 7Z{G9J z kWTt f ,+;۔ mi45lk&H^Z;"BZ щ$M&ةhHZ~X3fɰz*} @]4%_,WHfD*cs[m<%  '?+Z wf.4}%$Af$"1~l&zC\[?" q/Zh#%x҂ =q286EH>+8W,)eͅDUPPLo m!}k$^`b¹}"f+Qކr2=B|Eso""gjHXB zz!ҕDu4{p~Eڡ|hPnAL/H:@Plb0&fxr:K&7b]1?۬; ~../;Xؽ/~d?.RCVrQF^)+'H90erJJeW/8ZЋEX l@,>&ா\Sc>@֜+32P@.6 F/K|WUjێЕvNWl }S"1ϾTїJpjs ڐm(Κp)?6jz|3NZ IPIپ2-nT_xҦBp_w,p3ڽ?b%! rgDiVeZL ;,5k0}Ᏹll[EZEovɚ cIZ=t"̭ یE{: {՜ ^mN3^' !x<]wL7NЖۉkI<],'.Jz1 Ǹ0>Zy\=[UT9'5܂òuo9[EQ[Ob~.D`e/I|Aٵ7(oH >5mRf'ha <M5hJ/ր+='4%xŢwAd۽ߗG?$\לjCƮ\l:fJaJ0xVVN"%¤ O5-E!uaUxmd^ӳ+^6USw!d%/~o>WϿY ]Knq0f̂Lӏ:[a$v١+J57}2w[wdg| Nuc^h., ~ΖH S}ɿlS`{uY04-C*{h}@:ӊ<1<'C3FL&_ цXd ՚30;OOyP?|&1@klIc [|OW)6+ -s<=%-xֹ=#]MH$˦+x+G Vu״R8O M:a甇O8* $.g0n[kr8o 3H.<ᚁȼm?@_-xXU"0hSJHi ױj$k;J75$4cJaS < łYNH:>m?Sf%ld{]XF1Pz%.Ea,$:S5NOPX1eG@kκɅhJPqKWPEAoYisTUa("|ly(ilL 2|~|&\n-`D0|9S!~kԀ˄ah| uYC0ߡ|zkuv9PP0n`EՁ(EpJk:0;:w>5)[+i8ίM/ɃNt|&Nr*Ѡ:BI3MhWrܤWWܑP]6.' zptEBqBDkLO.WCbr<嗵îo,*\ivb1fJȞ|[I:ƒs3^EΗwI !) ]?ܿ׎l6l[Lg$_Nce>7s:gb״[ M`ꩤyE!<;YQ:.5QAVΖYɠ%\LDQo2oeE4NH5 f̲bO#FOێ,% qZ wIebw81=RprrsƉbEE1{A+}.6Т6W,JrWʸнwV8Kq}xj*qFX\VVR iC!\ބ &⼔՘D#a+^9JgxI5 &~9LqË+P4x/[kDpVkFg;7Y}L(V3m 3eIj P H02\|R?A8`L]?U5 K=L_gOߋHPKN3s=U>C> }Wgb $Ij9x:aJ&Iٜ:?]ۢӵ q Y;uʮuH0ŀп&o=jGD# % FQV EB*2J ]^3'݌X01&E$OaeQcY0j\p"lFۢN ,]7GAܡH"_e) NH%pOzYI BkB=)c݋)zidIIVgv=BsF}fAb]'oyeZzDؿ5j;ć,יQ>v\֋mf KI?;-MJ<U/yڇf?a+ 6]yƛ(.qsg5]XF4kVK;4@/LR+g0_moN`q{W}[BiqxW :YBj XN52v=ԍWieIce(@{cA^8kErAۊzʌa?η>/УdJh5l^XL~I PBkFnfҷ #Q[>0rd_i ԓvFtF(cxWc7Mt#ݡsͶvG$g;0vv`K{ls -@Ff56%ؒ%TE9Ѩe)t}PKZ:|U(jHrݞ=,i 4FL1=RIUb\@C=ʦ<^g.6*cx4hSͣ k gQHD`gƏFW:21YYQ+k ?];S[h"5fK\|+gJ)wiYЊ6Ⱥص؈0 o֨GkՖJz}uDP.ӯ$ud? *7~&\ɕ97?RҨYg25j X<(OտtͭdLJnnG@ӕ$Қ$\菽l :0u_')5~(dN*䪬]OMF}H Gt~4<$QP[P=Lc3,qKR6N WB#8\$N^ˬ^/(ydT7mv9CTD'F׃>hxÄ.E'~Zϥ]l}XK`Y˧g[(~b^ŕ %lA>.Q1 n Hbt*c6 @?B^a-)Ы9"866$k!Acw$,+G9ZiёӐlJP >Nm*NƓYJ)g|ʑ&3b IY]fa&~ˉLUl56s VVf({ pTՆ]kF׸$`AD X-D|{Yb4oi(ђ b 0C9:qToGyg=B@?qr8Ep3hM{㱡/:#aA5ٔr+rRҷpI|܎NnLI𼶳rZL|򁾋ڹú>zyfIy8GX^媆6rbb]h=-[E\S`~LnvnXő[ZuM} R}v+|%2R: l[J!*e_]b_-_Df=>HP/?ܹ0?6`xUyr-3vfmSuq.pS=qTL>ޤU~HZ7n FS1Shq|*hlBP>%gSSZ~t@0i`[r"7B}3b]#F"s-_p~,NimpmKDyh{%@/x´6p $2\o^Z'YI{53p+B(Y*|U-": BbsdveäOX[`:KOG vx!0pB7Ѭ 8PW.MFH2#6BgôƋ&g5=~ ۳x@E{dpV_F4+  7LkDsjK99[Dyr(2r ۵&3c.PMՅN5ڥw d-˖8g宐Bћ_6T> 8Ψ&d}Bq3'?gݱO GB|~h=Ejlr;(N~^*.h(1j )BmJ)#Rr7%gP!<i5'WV_|6`>?Z5JX e1f0B)37E?M>W%$TDWPQ77+^ZcE`قWm=`UNΏ)Θ6zGIOuxh7d.s[nFNyƯYJ2OCr!-lc kIMё /,iTm9`ەbǔ*G/R2vz̮|4 ^Z, .n2tl NqxC4$ h"F},?Eqɓx LFRw90 9J6'q5H.: M>%硚5|ri*hVZ"? ` b,F"Ю"MDG]:5NvY^&S,?> x"#ZlvLRx.\u,ٍ uXi`0o@ׇ`}ntez+sΩ|owݫTVxOsC?w>@d4sPMbF;B,}Ӝ}ZykGZ[8Y8'9 7n.FFX4XSSߦRa3k {ƲN]>ON=ol?-Cɸ2+#.> H1734jݱűn5@u9/HP@ăH-լ9OEK\$EAH[Jn35R#xȋͅbo+]a^Zm.ē:Zߤ! ^Xѩ !E$l Bz "i\Akd5 S(&M*^G#[W4WE!Ǜt`7ۣ*iA+KjL2+7#/Zrj"ْ)`h"3,2jVX~xqq=ϵ#L}ĆQqN aou(s[ {g A5!x\K myUrؑYrgY2GOeEW9>ߧco5i]e8.Xtjgj4Vqjbd K6M(YQԸ1Hxu%v#G ~L˩ #O/IV8)cv:GŞ m o (&Mۭs˛ޮ ljZ>]+b <+;gh-'WI<*.a+ʍ[ss|OaFjmH&gtcl"Z-AS|~" WwèҥkJM|p9uH?lܿPKug6&kDeW"K<ܯLg~i"δĸiQƖh],X\cⲦ~HoT44D!fc0]Wds^nj [`w fKՠmM1#wS.^dTmR9ن].ysݪ~EUFNeOS>b~dobH)yHߘi"EP~y7|UQA27#3"hAa ѝGze6mrckm$c%V'1١!PK4zS@$*>-N u,+t"ޡ#;EAOp 1Lb6ˡ'.؈[w^10Fj]dH#S+EUo}cAk&Ro mLIhh{/9lheO& :_ Ji qon[õދ"H{VZr)g ܎5󥦆EwC}=`D&`k r CIz5WYWI1%8bi''{q>#^ȿ`Y"CL Zh-)!xt `%RQҜmQDDL'E-Y.@ߖ/3sp6d~ -(Tiv> stream xڌP #ݝwwww Ngg-yڞ^}XI^(aoBWScf01201\lÓkAv<ueb.`Cy{; `ab@ dgE<@.`~PR9r@vycK-jo xO*>KFFwwwc[g{' j:;t:K(.f rB  l@@;g fJv1 @ MMm'L95Q&:ظ00:ڻLtoR[ _ nBvp0g- _ ~z9@gcg's 7_6׋ӿۿ 8a?_'I?sŚ:寧 //ٛX} is&DM.:+hp`7ʶ8Սѳqs=\xKrϓan+Vxp];|z5=gG@kfѕFfqZ!mc A|j@y]Bⷢ^wNfnp {onodOz o\iY{wŐſ),%?qP_.~ W |0=޻jVwz]ԺK {/l#:d7G7֔p%Ů͸ͧ ?/  O|Pwx"/V`Rl* ySne9UDJli~G>io(7e[#=I5~Ftt<<cԤM>Ȥ@om%o UmOX4b0|["jXۋ58wo6]1"p⣃7XP~a6cu]h,_++ѫ? >_V!C*zOJ|1|e_*PӘZiEcj Of"AVE%LPA537&cGB_y4)!^D$qGRfAoPBD謳K)PI2]/[7J& !R*)amd)Qd(rѲ7xTY%YT8r7/f b)n%-?j^=,*T;UV^oesbXLo!9M%CTuB h:[^ JPvmXv#KIEmv?}M3B_5)*!bM6sޯ<Ɋ5xr#|*>Ш,>n[O3ly-OQt9f[6&&tRI5\}nuz%`]G ~'C_wY<Θ1BC1ٟ~OEliGb8 73}G 8J=0,M`$@CiEAB@/1Z*z\bp˕zZHg5;Q?Ev pgذv Nvhuk[MZ졑D "qgW/ \_\hVU"{aWT#||G"o0AHxRP-C]k?@'JoK.Of.Obr}WNb$ '̇ Iʼz16eHQ됅D.B/ȏpl렎DA\sXCՠ&y`=rf_$j&Ф4Pݥ-^;7#Yƽ$ad>Tw챕eM4_!ةu: a.i"nOPDZ͡O9E^1͗_n+''=pMPvP&ǘc24_J_5VK?)r.qE{JPMv#"uwFTz m!+v&T{ 5oz~ L| =?˚Î64峲,9z"o׿ k^A5L,ȳ֜BJس%HCTycGٵݒA⨩S}USXCMZTڊ< Ewq+P [HR7ygc%@ϗ&&3V(ickFcߨB %`Ƭ2j[ًcgwXS,] u_P2I*D{ qZ@9.SJO'.eB)>9wy2?y[]MؤpZ_ ן㱩`|h8DFF*Ilԡ9{7(>ieo(Q3:8 z;΍Do̧~XUz9B.j E;J.*b3a/X!Jܟ:}_$c&jSB$xcVIZ̷u7%0E(|T?%;B\  ߙڔx8j ݜ4>hTfnњ_0y?"xe!zXA- 'tA>}+\EiNwTi(eL1"Q?f$7(!nBWA4dZ{dc]@t6Y!{}jv:,v f m)չ|Y+%cf6: cWZW?KʧR56 @z3Q|q7LP__ڏRf|>}0p[rʁuw,8 f x+f l/Z񧱈q(sܢ֙ "CZd|j9dm/%4y]3}SxVP] qqX ;l{/\ͯ>_RJSxuKpUe:5PqWڜ|aNZK9(&El`|z8' qzi[*4P:5Z~N"L!hI֜5cEE hOJ`JmVpA%H ju9Û4vaNS$_7y?'xIlj҄[Pŗ$YsHAUlہ(sNjC IOl4Y,TYԁ/K 0#88Lk :+Z#{C"!c''oh`nB9EGFTJ(#P %-\1Ґd7t)#FGEYCԦ+0k?S3^97eD@2 Bc5̺F6 2]؋CmΝ'#iEe ~l4о#Fnೕlv`('!d>,:իUH7": H5θ]/ީZِTnO.+{@L:oK=(Gԥy]g_#/J~KMn?kPV{\`"vlb-+*z9*i)9sLUj{sQwqƀ].yM M^k6Y 9܌4 ]"]::0ghJ*I[R"ig&;nT閱o*hh!oͮck_[V->j$tyfq6bQ-mX?0y(@An$u;81BUXkѿ`X';QozmxYxΥޒ1*c- 2gWHlaȫ:F5P',1n83 ?Wn5m9WCwdaQ ˯G s?L'w2NnWcx]= B\L|Yq]i$2 riLDy8Q6qL鞛vOT ؤIC#:؟s0`8%hlvW5},ޗ32L?"}W& 7iѪxo0O:}u;pUN To>}B&h f_7A{VJDH.׍KՊ$BӭS~-n6L *,uMR7<"T[=4:NFqA< e8-'HAv 0fR>_ƭSz,fZ:k}w´;P Q;;y6[Bӹ̉6%9|:zݖ"ZNsDyi[3W@S`τфFζWs@x3 \s|BkSmk1KhQ$Pr FM)$O|2-m}$X- @Le\@aVyR<7_LS3Bi6i.J ʩk7Qm:SaHC:P[$Ht#QETe:K-A0Km9; Źlo `_}c 7>01T%܈j%|G>HGYt_zW}f[W+"V`?fK-2ݳ:/T=lBӠC,]߃RŭA&x'/noo6||^A1W h/2YVӧ7?2C<Ĝ64hUi[-*œh"ٱjJźCJ.tS :JI2ѐ9K'D0]yl D֗)aP"o/dy\I㤫!0]Ej] /VIÐ\Wx (0 ~>O/(PQJ Ea4q[~RqGS-ݹi#yeD[*3yPc쨐X<[w$,3 J=܄4EgA1IWAS̏9A~Z[33r/:i+oxw?t{0QeG5[5ִNw)gX9n8n0к}RJ\ 2*?rH~ax;#@h _p-LTeھ)ߐMR! }gu4`G0jBe7;muqVvյu m9p嚤դGxZ\u:AKN/]rfe|z@-~NSIIooVF T>+逑pU5n#^lC-DL(G hV 8CQw(2vn`ӮHMoE>,:gO J lV8Lo XKfk3T!f][IgJv lIA9Ȋllu)m?$7ix$@[~/F欒T@qN(8($iw<#f}Rk蔘FjF's~-%OۼSEyBG~![Bnǰ r$7EsPRKEO!oZW s[[GԹj֚5*k"i4y*˖Pݯ'(k-)^ w8dUM 4)fQ$ݍӸc;=IV`E +~lu/roŞw ;9_Iѿb́B\X}3yc++v]yک;7[aΉD_a>1QuĞشӈb!0<~jU.QGDu^0… KaF.#z^'uE'Kғ{v 1ӂWP?`TYjZ`"`.Sf:qƗU/ /_L~GHz3i;WQ e_L>&G]Ae *k,v, lXYTt'a~5I02*i9!-SA4jH4_R?3'8ho3[ƥs>/j7>eêF'J}'B7 CWиA+G{ ֛p؃AM֚bi\jfܼx^f_1zꚟ9]8 k<9#F $bU#Ug]Њ6xT_&]jlDݞBF+'NmrRʦ],p%-c\Y-vϫbP2 fh+ 'd㻁IĶ|, x- Q>M}G5̉\aVmRhʾ9 .QH(yD뾹KZ\@zDL)T!ˇx2jK5lmG5xPM: <n нh}Rwzs!kJIɘݚc`3R\91O4\rKWU ::/'i]5 TsoKQM:xfiy6:215\ܸOfG`R#|AdAbmb#!Q_썐琗U})ds]Q:؛W_q`Yֈ-陏.<-x5lP^˕,QC:} d/{vg*~},쭏?W6OqxO g{G’hܓ)B#W i4 C.S6'7q/nl<8A%Fo jK“~Ne%O= ,>H[#<\HwoEM9~ u>!O{z?)'Wx:$F%ٽCHH˜L@vhjy j 6tI yE<A;C)t`eDoB&Bq(P)(6(a$u yc|c2+a^N}I~Zj~L[UY։1mR2s~*: HQa>E]L+kA,Kz}m@DnȐ IHcF#w4bh}QfZhʸS΍[E=U˗ KSIx=W$UOV*+nds'MLH #SQ1ߧg!E8 G֎)u~M=d60dL0lV-l[2K 5NP3E4һwK)>:b~MYrXb~ǵ=XXC25C%UèwY]kr6)/H73^lx S,AWOntf7, S"lC;GuRԸv? A>XܪU1 y&zXzKpV*-,C!܊LPˍh7 _AX ~MA{8(7BsפyVsDtgN;{X@p"bk@X<{op>8b0t˖ޗEFrS~/y8Lx⼛M0˿$>x"ԚuV׆gQyV1O|d(K1GVTtEb晑9'#^ b!45[<ˍ q=^F6e2nhlb߷ +_ AoW>Q(SԪ 8]=p-U]mEr\D6ҞP]ص| %!w 8\Be${}i.\̬4扭,n7SO+e~|mH\L@CqJQtZXi'wm/]D e<'/nArkN ӚgP>Hv?g!UJ!ƻ꠮B7%N!W\Ā' q_󤎉N Z.S |BAr ~퍻aHї.T *X0t{>Y;!ǛPdVb$&cھQZHoM)m8ǧH$‘Xdz8 &2-j3_P^Hfop=#j$Y̴ qP̣7CN˻6g"Xyˁ G!%⃌.M^ꇛy9!\#*Ff+@.Og|2d3Dr^g+*eJȡ2?ɹO<]YJ0pR0 :#/J~.XA!q,v ZPެnt1;&cO$-¼E7'|ol,ɚ":!G=k9W*͑[Fz_@E|Pz2EZ9kR$&2)E)f;%z};tR`K N;.'3?i# q{]nIO%=A/(W fN[^1izq_Y ^R哔;8 aPT)h>nq\DRdbb²{O3?IXvtz(J,-PwNq6I@6BD!{bJ`  $lWgU mZ~$ <,~R*$;w&ȳJri0%eQ$xs+Bq[U'}5j.Heycr٭!2e"^9sĨ-X.V;:Qz98x3p_T,0-kTE.oNc`-Lݼ|Ro,h:wF}IGϻΤMyDhכ6H,/tuP7 ) 6$dc:|HoZg7܍^!yG@b=(yTf(q*AqkƠ$V(F?ޗG(Q8hevq7wo,#yZ_cU$2˚ DzKr4E l:Mtk*A 'q?@Ct6|ҿK* p(9r;xQPm8@';{mvO"b^d[5nEqa>*nAW*,="n *[ₚAmebWVN_uZH NH;fBs= vDH+Jeťgw#$:~qp \,?I5ӎM 0܇>^|ѧp6tT _S!Kp^SƣQ:=,8 x"LN/߃^֏x-60Vnd:FxQ'!i lM%PE-BnG0&Z@qdf ~2% [y"ZG }f?jC~H)}&L|^b$@)_uY'3̘VNHYνzVTv BmsR؊ٔƵ z׃Oi*RΘw1u Xjȗ0$_|_>[pmPRwbmWB^:%xGhyDpbIKz7`ݧ-iVq^9Q #7q;u=Hři&-7]rn֏J.{jxۉॽj2q<<%B\T&|S=P5{3$зoQI5ˈ D gwog΢iZs¡_(l|.AqJ)l4F8,6uPۨڥ-&x'IS1yAn&$O !(L k!q?^!j,.zmC|M^짙!GٗnR~5V[R;ܫ+FX릚vge/c 4ƣ֚5;zz\W𭇍ԌN44TXlJ{Z0}I۞N {ӡLlkJ )(=K-ĊE-tiNn~+(N6ΙoZ:A0^*Wr-53C7=kCr;6|X/84ҝ&9^ 2T$*&@CcJ&X[g#/}Ԁ7GTp8tP͏WHt!&_>6~ ҷ׎P+|I }|)AUR9 j w&eiwuMIT ʩ̄YD± ݌HiT01tISȇ/U D;F<| a"f*~}|c ˀU{[u&U$xM[[qMDm Kݻvgh"yKkrXn]qehWć/QT/6wUBEL%_>D\:Lo:s}L(vIrb?74 xouo^P{nS ,UŻ_*ǟLڿ~ 05PUB>~Jy2n9 :t8;UsEUF~ nϛA~ՌjXg3ei -wxuQ4Yɴ\̓T F!~m[?6Nu_ i+M.B=QNC!oWs ^j^@gT&`"3TQT765*rf{^,cR%fc ]k$,'0^ՁM\M`t<(,.z7趥C9n7'Qn#N\q{5e]&| gS&柘iOWߩwa%=+}r_l[ k؜I<65ș٭#m*kNB>"jG$Ub>F'~lV`{tXZJMPLX`Os(= ȪU*ڟm=BSܒX@+%ſF#QK(n\U!_`wn(T] wjfƪqZ]x&IiǦWi _y"=r-"TfiD@=RQK,H|0[Ax$/}",:f|wF0̋K<,vcvw j+};U()tm':ژJw A9zГgeЀ؂X-+G/7v@~"q y`0}7l l(i^: s.u!颂3^r !v6Ϟ:35 ȥ$=YXfD#?_<σ=i'%ۧT/ A{iS %8\憉tjDf}ZXEX_0xUCmU MFEwC]&%VpOFZИiWm+'R*+o>;ɟ 2T=< d ee$yJ~LF*`78D6GR˧Cqq:|`9 ako6&Ah  |!Ç}zg9Td)䷒ǎ gaIs?%*@݈vz|Sc)P+K2Q"2ۚ fEzu^ߖ2gw^O׎*:o+Gկ(-uWݟgށm@oζ(GqYE!/9QwFgr"V0ɂE"ڧ4$LJ %Z|3F;+_:øX0%vha4r T!uB!͗(vG{0p~_\'VR2vq-*>iM*rpzht x-A.wQ 3N+[ko0_BQ4>o_6v TJ\CWC(D4ferK 78&O4I!= Q‘D Cȴqk=Q(A Ҵ{URpo pM?Y0g T%? #t4&IB՞jA8'9b8N 8+(@Ѳ!P#T.*4YțzKbB8)@G8jEYtRzc!!+⸱e&+h,_hzmO=0FtTd+bO(p Rs~BV&MBFC5hx DwkL5)GB}U uk5NZ=d%с}$I@i{E҇K7*[)Zqw-FMKS/F: ։_9N쒰~7ZZN T %QۥҌq'%-^0a;ѩdWU5*.2DEkcXsa5%DYtg|v{|| 5V~.U&[STmGrZ[¿*d%.]zJ͑@hdb^/Ws 3ρT h.O[+^3#\q,vcXη50.:G(0ZUOXSʒ*IJm> jPK"54Q.oқRO :tQ%t'bH,p 3-]O0Yf8M\f~׬}zY{g짣$ŔGO@/7fї_ $6PՕg3ez,kvi'Yi2Dbg0N{tJ#XOjZ9.zR/i2E6.4x۶BsZpڕK[JIduĐxT+-p"v=5ʟ)\<8FObvxWspAD[r}q^knkX^\AJtm;^auG}Lșp](j ,U)Ugl?$I|dvj>EYT"-?us-^\BXb2,JUg`c \κ8h :,w3 maepFLs08$!܍0Z)` J=\Z~]5NAw e:NI$Ej5C*݅:Y;ӥ,:sDd* uR'Rƣ$ endstream endobj 258 0 obj << /Length1 1976 /Length2 6992 /Length3 0 /Length 8179 /Filter /FlateDecode >> stream xڍT6(SR@ћn-Ԁ`FZA@AR:QA:DNeDׁх@_vti e/G#G[/n/FW,zǹ}oѱXܿ_;͋nD_ 䠈?^u.' beC &Iqw n/gq #[K$z0ϛ ,E*ˤ8xvq Q.iˈ憏I|^ ?%YyyYclWrxe#<隳 ϢJs/ʆ|V۾-v1ڒb-uX}8xo`4I5HK }~D+ٷG-r?5QȎ L免z?iMRlb&w,1¹W3:Zwf-E6YQM5ľ`q'ᄪ4nI7ZQ̐C.dM< :Cg,%;LwFFYxnoh[ oa<{:u(zp}wҵt:atö0L[o݋zp3eZd$P8|ߝuF'Y$-kGbaڤf㓴kY{C 7C[Rb&w=kb-Ư{< ;|y]Sfey>ې+4էseJoO9'>v2˻iFƥKS|-i,1d_դB2iq3q2:)znMLT>r/0:%eHΌ2!Sj]'/xKov#\pG(U3\^31F"k|U+]E}Qmwa|dʘTͷNj*0H˕D r`56`8?IwW/ex.X4ACkVƾRCb z3×zW'•a6j7ţCv&DER?=>I=&ˋK:ݓI3tO5œp! ❶+Oa+`ia#R%_ N7Cm&Hq{v:-d7ƠsTBX0?EF>S%7WR5i+H?ּ#i+:d~UXHGk!G]UIf߾w1#aZ+"1ƥKoNΆ!%,vidsOfb,oΡ8xڥ?~i9 #Ϟv$$DVx6i . {tI7C9"ubL9 u'2~Wh:S> qe`-?`>H BڵP2VvCaPIb6,g}02R[6c^ҼU|NȇdQ_#h#A9{-ɜ"VNU{gu^1ˬa%V 𷡃Ĺָ1 Nuw+&S/7Q7Z@/mR=uf+gA7F@#DZl=%bICZ4]8#sMtfsͬWS!kw)=J ^ٽ n?dF45@ŮnMGtz`(Ng%D9fP2}zckq0[qQ/Iװ1'Aj1\ 'Ͼ@tE{Ԣv0"}M rfD%Kx@0m}xTb[8(`߽p\Uxg Tՙ9AZY`mӟK׎oUƃ&+t/}T t>O8`bz-/6;q%T01sgMDnlS fTl=f_)i|g76}d%",̀f 0j?kE4=XzmycAdhj'"ߪhi4?ہQݍ$nվz;gMN\zʽ ۹`=iS~i@ cX˯ؑYGajMVm؄|v24RLlikm'-$g~x-=oqW{/aOJ-`b^)U4%Z=~A EIfGîu vǭg_ܠa|ё%{<_aGcLAƟA39_*M9=L'3郏qmqX)#H|\1?ajxoPaJS{fętէ$Cj 2au_5^= WzOV髮Pˍ$["4yAu,tjӭ!{4JQԓeKdB=$;k礬Bxikel5 bߍu)90`Syl#Aɬv9ΡN w]ԩ/QV yIQxcwj;ő݂+Dr#8=X9/c/e KtuǭQo}KN4l~)UDdya3[ܓKWG= 꼑W|SGJH"=6 gYe2.m(;6Sd,̶IͳQfEf\~Rj$*>3z$&^z8/Hj3`VTH~e9ŖJqOܯrEp(~F\fuqTWyֲg⦭Cyr0IO2?Ь@Ʊd i왐&U{!öOW't؉\z=xEҞCX V+3IAїDkyz6Sz~X9<\eKA>AE.PL'wQ+Uǝz{ h{!=Xȶ~_dr:Q$# ^ =X` 5Z5.fG,gM!{՚]HN:>6n\9<'ynOAW[j넰4b _Z&w\JƐܾFo˂T\ȉ܏ {=ݲ9 @z.1Jb<ܮﶢs3Ê81Ӌ!0詟x@>Kh'gpeٽ_@f"m4q˯vg *8QG+n+`K-o4h|Ȝ-{W[UH8nG{u Zrg ꞚWG^W\%*fx%, -9{[|;&n~^x㤺wcπn3] Տ1k<}%uw z_&ӻA'߲/ zs2ΖW F9GҘ J*4RlJlh۷L^O(ZyR nkKEI\+a!8RvFɆs!VZRO\q*FJ/ z +yD%FfN[ڼ,E4rˆ;mjvޱ 0%[MﯟN(֫6keߝsgWϒ~2r`2W% K R=gR-¢$ROn@?},!+`2)YAUlNB4Cv"k&۱yC =nl^޾Qz;iM0Xْ-j/WVͼE6޽p'ms{iF<=Vȯ]b̙1/]fxo}4"hIΣ!=|IC:A4p!T׭œ15WgEc%2Y >wgfwofxcǒȞ //2m&^}N"R8(lj "R9׎v0,Hݽ{RmӰִՋM1Hwt*F$ })V|ɡ gpJѻg,^3WflI87Vz\{==7d8TB/;`*$T|Ѡ:{č Sgc|dw5%p"Zl|f6T,bA*yvEwOxxls]@|Mh/$ 52L6w㜣ۜZaoM߆&5=[!)4Ypm!ĺ? "SXb:{ `[__Xh}8{4W# fK'ZP6EHN,E˭#nG o-C![{(+ p )_ !zxCgdoip_|iI9F}*Vusx7q|H'"mQz=fzģM}}};dOo'\j~ia:`P29);Hd(GqvKl0QK 'XS+4$Skx֍ʊ_kxfK,'fTTق,f1]Fnz03h)30.LwpD 1UR^/|>fqVAm,%YF<+5Lڶ:dmb۹A@ȻZpo*bH6νOs 32zY8>C8|}+Һ+k?S]їrvI:=512ɴMno:KgIB}++Sd'U*n+y,־Rz`IQ3_A*!u!dio$ x;|HB`Lݵ䕗cǧ%V”iׇXfz|z5{1i$ 0TDwZM?}Zvִl#T=]o1؄qrT|X9^5r_ԍf .tJO=nqɍ˻iި:IHZϷڌ.IƯ72Z U|-OKɞ\  bs<ή~t+K,"()b!9X;&& Rjb/P"xJR0T_mg ZNe9 #th-#ro_]d4~J%Em#1oQ{sfBa!DhW@pM\NY/UW;#jVax' endstream endobj 260 0 obj << /Length1 2570 /Length2 11947 /Length3 0 /Length 13419 /Filter /FlateDecode >> stream xڍT6,R" t 9 R!--%~l<5kuu/ )$qd2DTU,,lL,,TT`G1:: @d96i'rxYX,,<1D9&4N%u[8h@cB p1كMlrF k5+[ GG[^ff&#k&-hP9A䍬AWƄNP;-W9ك0lqy8٘0r,@d z2 @`LLֶF6n`s(29:2lLA0#g#0fWFq!%s0::09!Kde1S5w~`{ nOb0ۘ.ɖYl&B,,,l,jb;-/%V-`+6~=AG{'ǟF@ l0m 1l`W lߟjq{4kjZrWNX `089<<h' GO)3(\aMO柣A XP΂4+b?/_.;m7!q'/5_ qNj>r Sj`@o`W"[A6 E`vL`lR`lL+' F \`3 U0ڣ('Yo `~D\fG `}D<f Y,R.`첏.`"n#)="#<"v#="#i>"XZ"#aF;X=?"X0LgokǠ+ֶ9ң ,/GXW:31,d-=@:Rx,_ 7[ 0g Y?B )9`6# ddm2# }Q 㰅=m W`)؂aO?L9cu'Lb ץolB##tu<Y1 t0o> F8~vi3;Z؃XX[]8b8=n8Wi‚an@\sEr]&N8Ăݖ}@ Y _eu@m (+;Vy%Ʀ󎒿lyBX~}$dKPۂdf9w ĺ-ޮmfcjNxҠ%aX1KPup2U  ɤp+)"3fz yqU7Ev3u4֔ G*dG~()ldlˁJ0Jd٨R"|958gݸMP *0m]h#.!7&o*?u}Dm*%M&omJ_0rP$B*pp6S*ۣzq ImNռc$k5N[zN;+wvӈUTb"ífkIOogF耵dtηyؓ#}k@NSbZ6 h+Fo@ޠsBBV;p8f'. 4iőQִLiROL$:}lu#vo:/$Llh!V)3gG? v>?'$ Zl.ŝ7F1wvWnB ~V$}L;7E2K剸aS92KD&o:-u?}6 &ܧYeZgdXҘ28N,lNjӖen. P}! i?+hIs`0@WOAsdgߋ,J\Z4UlLzwO;3IcUܻHsR[ί:\5TB΢g%en.z=œJn~CD!tdRHbVX_}MHixj^fwEK'3rᒍf48BېvF;J8 Ik7uξ-Xll8k]*s zYի7h9m ˢn4l|9 [ Zf\JwEJԩ t ɠޯ)h+p&Ng.6g+'{hA"k)cG߼iEN|,2@bn=uF%1{>r,ݦ\&}ԒN)U]43_lǍqm B$=8(Wl;WE4[0.AHWc0Qݫ`99ZJ,ϝu%-ui cw*êα폱`9.~Pwi$J*_:[TVx*v'VNHݷzܭH&责3^5&N,> qϖsû r4 b/sV]B@겑-ÜΈKG;3svamFjg5ymqX :61wD!)RH@ka&tp5 N\̴;aަ 1R’\ t~ZE8n*-ٖ:ѵx3 I7zs>AEZKksp#'W%ci4)M ZK}w6eF㮔$)O4fl8냾H&4+O N0-T Zwcq5*r& f#m|7L{?1%՝A{43U=*ǐbgwjwQcwö'36v@# ߬xiʷy_9bP"NO]ٜjޟ`f*4qz)k4*')b כp%Z.qp2+6j3#uooF2/5'QHuYSU (t d}硣|uvpDAڲ_6I+8/v/Y^'&e:)A!ϧZ_[9`;0lߙ2?ۓE<7 7*fӏ4!^ a%p6ґQOά˦E]?;:a/sZ|;4 EO#麵cVQBm^ZF~+0j?YR}a^.ըGvY^!󕚞M2} g5ITJjd \Bα IЅ|^Ɓu-2u[ʣn;iRt@´  ӫtВ_Ee6ͱub٨Q#Xϒt+ ?_ɌjAeJ(^=kj0`:^C2:Uw2o>?솿brp;U_8F6X7Gs"\S5XI mR=5QwN7 p Yq7(ÜgcK- $#GOSU޴|κ;ŋ0 %=ƤoŧM,6 gERL*؝x`4f кRV{ɹ\Ut Z=tP« {UXXWCPp̓*QvDe%nh|M7CD¢`B.RuƔi!(-in~դNTFZ}"ǹ根c`-uzEEQVd3ѣi_Xa-y6q"Z(ș_ZG.ak7 vĵ(Ew?[AghU -Kޞ#3O3@$iS(Nnt>qMw6 La{A\{y8&M~_V)F*ǸF%rMXUTP8;9"PQ1.BAI}) ޭZn"@a[)ǚᒘj7o8s~El= K jt rz%_B\$TB`\EMۓ7 c+l8p#4 sAA7yC]ݯ4+zaFt' qtY,c)ØdpM9-ͻ~ٸ/̟|j}h`z-8}$D]}xg@=IpszbJ:] ?oyy|i{)Tˠ<|@g(i$]fDr^_%[.t; >UZ[FV×XS JC-h$է#ɫUbD#Utz2̸+Rs4rSϜ},h:I$AEfcP7Ǿ |0etiV9G\6B@P\SqMDuRô Fܲ5Pdw2׶zo3yi=^6_1 뇩Ee{sBMsQ۲/5DGxM_+qŢ:W닡fu/+SX2T2VʫΜ"zoר88%HWA,q~4d٤k~8Gˢк/KI{[(͟5VoMJ AmGEUnVKF(by7$E|n'x )H2I۵Nܕ)vۢ[Ok*SVtGytc LCI =qTjJֵ<~l~ֽ'|]\`IͫVqQ[;eUw_OQ" uÙm+}fH+A*yցO ,—to$qL>_p %naNv:vqH1xd׿le]罦W 9#ʇ ߽Jˣ%S-%ISnT@I$V]`|W0Z*`Qb,1T|I~CUA[B̫&J<^)J6$=w"z@DMdy\8< Y]ڝumBǚFo Ozr v^_ץIGN-Z{uǎV&MPܟb%s}+FVMS( YMAݰCe[qmf=N<<3沍w&]|@6%J?tPA1+UPzgOvN \E-{*f!#/'WG&=9yQݱ8d&rWڋGL,[Hv'90I>^੷v&v,hEh -M{Q1DlB0>-ǂ _eI_$ *H[ka ګ׭\vo3[KڧƠsx5UfW2{pI@] dM2nt9=P$Rt $t8}MvZi+J:э09GާAM#U/M /'TSE^n[X@uW;Fwޒ* hq$#־K3~E6$w(lK_H%k gD8L޺_5l5DA|SaG嶬=0\W@,FW&8Vޜt ˔-#Xf«wd(? OZf!FԯBp3'gBfݼTK!r/ArÆO ߽"F nhseB]6DAfy#go`fQ"z?^jn᭚:h$&MPGtw$QM+E^G|xڊhqdDmMt2fZRM(d]*tx+^xpwb;u)ou %vR g/5 K>k׍m:ΖO9\ȑu1׺δf 넋j3BCEp5{(~dN2"2" vI*<e^@t6gp&B9&~sg@={Xܡ-gRϳ2 2y|3:MHݯyu=9 *:ʼnzZ%CyGz@]NFWܚ8ScaN%*~jYq MVv[G-65!g2PӖz|@A:3a(Ϟq~z)V9`g5jfߗj clӍfo(E%t,ΚL\pi |f`fs]lӊYIbh}ѨrBZLjդ S:.6~c{/cIp,tj5/p{ȲZcT:|FT2FR̕xXgIi2vNt5,DDO-O7zC뺤g sDh6);)o6쐝$3¦0qSh&ݹaP\ WC^g}v<{K`i~^zZ8/Ըs:;qq;C1X>mz&A 3Ut$ELr_r[̖t#ϒa;6= Ba1z,)*ȥ))<8Kh@aₙ8q.cv;Q6S_KS%pŚQMrmk~~rp;֒Y.025D. RMK+>GK2s x ? h>(A0ʡCa` gN\γο|ԯM#āC7Fޛ/]фª̒ATRpL-)6R 8Kp|jsҵQ'hD2v]d%S+S|)%'{8+#pux:AR;?k``-pFbQjFTՋs䢅\(͂s w5)07gLlJW#d5NO=}nsOr寂ܸPqG{GLI3{HA9i ?gSy*:EuuW@{H$yEtze|2`%SM}2/T?PfJ7|#/-T"Mmף ︚"'r7!n;-(3$jOP%ޟ/O3өt nʼnUy`  g1 9|!U@Af tVd2IJ5"Fz e]YQ!L Bk"i!1n99%C  ¿(;Q9͘>~V|Wd XA#y=FKڰBDDSr}gX*2H9tEXQj$@zCn^|bH\uT;(U qwJ#K6>ƕ^Hb/Fxjfd}e- pU pP-fBHt1 b(I6nAn @឵\fIRK19zS[ɊbW[;#*8vg6IFB8/Ӿ5-OJ!"mX{NոvY>3k#E feBK~ZJ϶cY*O%1̵ͷ.T4ڞbyq}2! w-6oP$˟CozXLrq!10fX|rf&خѓ.o7c)hÈe@}Ғ,~ѵs4m֎ax]=v٨/3yXW_Z-T8aр H"tyjϟs./]Aa-ۊH+S(l)ne.4ť5kP #^CJmS/.2߼zӀ\`=d{1raf-M#¦j~AUfFTi[7׹JHqE#Q}6I]zHM+a |IoҀRLM:Us9bн["B?b3kF-d}|)NCٟ7q!07 MPbG|HQzcu̷'?xj}bb? u38e^N^X`rؕ;}- ϿZMu{+~QGBqZc ?` r,g<<oAD1"mLQPdK5V /.H:_ZྪbqҎRQiha f)Kg:.2*< V~8%p1 j**~S$[h7zni.~FF&M^oK߬OΚFs/ t%EE@k8KtS {CfvI9eYEqiLAUM|ЭYXk܃9}DUewC?$}m<O~|5(f(0l.Nݚ{]Z[{ԉcTc,YҀy2 yx!:MQ:{B$*%5q^=n'M{^hmח=q:m{|=d(HR·meJxw=hyRgf) Cja f/=FOMi T "qwuNWGQ[2 -{Xvԣ߾޽6o{'!jb8^UFieRxb)/ӴOe}]e`dѪꦻd϶|n]XFU OI?yJ.QsǹdK&AȴSj|/>3s!j;5ԉ$'oBbHNFհM\Il-ּHokM4P!(_rU˄vӻFOvҞT@C,MgO0 < |:žqYyeb4Bc %8|̚;zarS>R[-,z:;h] :A:4Ⱥ>>!;'eЪ?=` 9[ f\UIM<v;V:.{/,m!U~LAAκey}S.4ȺR=d&M'prc|X;ZvyRMfWl@EYtj[3l͚ W!*%CU^鉸%- Ss=(}b|ƋdiT­O.ܛOc]\KƼw4ޭ&0&R!Cʙa3dJ]ѾX+[\Lq@x F_yOL \81H;H^?^#v!*. >uݖSߕ4( U%k] _ixGZNB6G{sګ=Y">3yVJuXRwwSa:}Zמ ʮ#hP 41|NrgPuQA\f-W>!h(q}hkP`јE >ND 'f.? .u_OS~)w @u@3?%܈[ w[mN%Ik)Rt˝ 퐯Ij Ǿ$_{MӐWv}LRP= endstream endobj 153 0 obj << /Type /ObjStm /N 100 /First 896 /Length 3201 /Filter /FlateDecode >> stream x[n7}],0*"9ؖ ?hYGXG $H~)Lg6XuxH{FڛF5ڥƹFk<>sasjBħM4I1tpMF;FQ@P4XЀŒ(!OHGE1Jz'Z4dX#/( PhI7gI<1#lomGO FMNTcF-q@ LePZp ѫժwz6As6BQ4e.02 R#gʝ>iN5Z7X` WPaC= :x ނus>I%5E'4a4*b1IdoRn›<[b}b%#BX` XT,ȸ$"zXdZ+wMSѷ=$\ 5wuʱ C81>LK` zSB*kk8K42R:3ъaa:S(1R#[Si>GO{ تy݌]\6)Y4ր?0;=yh>m0åI$pOoI91[)R#cǧw&f|Ќ'<4sd6Ox('7>~qr/4L~z~G}A0'۔?T+nnnNH~׃_g4~~{N,{-7rZuNsr gnۋ>ܤM'E;Uh [N5,c8Fm=ooX`\!qE)F 2CjI+_n &r05!XGPdaRVAYsJİ\{s[9 tna[V RB`KXU)Hf$-Hl&V#|c2Sn[jLSVU9}᯹M.nhRˌmͫ1{LZg\&i%ڒݒV'ڰ#e[: 7f'/b'%vj 9%"re SU<<B[ųA⛰SVMn"<#Fu9 #XwZ)5rH{sF-/9m9+חڎj ;fv÷[x v(.:2q[ jlqX˼@#˦;g-44$d Cpbrh.GnIţųE Zd6C"IBjxlӺ1|sFĤD!<6֒jEli%JV?JT򋢆_CdJVJ JJY$dO ds{-@WE!҈$ ZPR'p`@hd!1 L&$Dg@0j*8B`DDD eE\N٧ xvE7_ƃlra턍{|X\rccUbvFeײDeH(Y0YŬu)u|fu >[ݓM˵LlʕҊuuCer.DIz8{/t~b.Nɽ$* W)+d2*x_338sh" ҙ{7 L;$8?$!Rv)#ZF\2WSQQ|nU=g xEes9wR0TRrasf* ,YQʈ!#2DJ3=XEwIYTw)ncrwKYZ8ʐyҨaTi4~7X;1~5'{'?] CdW))O&nSOFG`:#xsq|#87:9@֌={@m=;?+CнӷO }p7f'qM }`bLc=@ך{/^]^Ƕd>;fˌSךXf2+ϟAŘw~|l=8k5fۃˋ |X3=ך'.yF{TIn$7P~Ye>eƍЇw(֌HXF+iY*l~yFy~u?,Iz _\?rum~PE98f}q}Yyh)mg^ʼ߀~Vh=>nͭ/dՋ֗cUm`}!/^W"n7{?]v ®._ :+㾲1K/mǕm prhW|/g endstream endobj 278 0 obj << /Author()/Title()/Subject()/Creator(LaTeX with hyperref)/Producer(pdfTeX-1.40.19)/Keywords() /CreationDate (D:20200126175809+02'00') /ModDate (D:20200126175809+02'00') /Trapped /False /PTEX.Fullbanner (This is pdfTeX, Version 3.14159265-2.6-1.40.19 (TeX Live 2019/dev/Debian) kpathsea version 6.3.1/dev) >> endobj 262 0 obj << /Type /ObjStm /N 40 /First 328 /Length 1174 /Filter /FlateDecode >> stream xڝWn7}W1nށ kר;p"uؖ!;CriZ bp5;sΙ3Ԋ+byh= Lpɤ0-33bV{&fN; qC4QL?V i3–bBsy"))<by^kLK-!=P/0O9 *T)[l9s ^T (P*A ~``5^`a)/|0^԰L/#d| yb&!{Y߬Or g/VvC|2=5R?~|g$<.V8z/o?:EzWMA/Np;/!%= vH_F_f'Gxy(x>k֓pNUWpk $]\!J5"FeEZuZSq.*L{ [ I=Gb*6|H <6B9172E7EECB1E472CA393849EE99972>] /Length 674 /Filter /FlateDecode >> stream xNVQ?3"2 2 " ( < 216&ZibTcc,veb|M/js13;Js2TZgU$` *22^*d]rT6I#Nyxxe,1BR8^ ^ Bpe@Ez]7}O[If<耜Rk6rLnQ÷P+Rau6ΦspdۭPoh*n=P B:ĭ@D9\RhMem W67%O%\QQHm< CQ? 2nw?kh4ESU*:}RnA^U uAB `\%K̙td(Pp;n_KM#5^#5Wj}Sj=yҳ"ICԒ'óR˞mHxԪ'Ƥ>= pkgmaker::latex_preamble() @ % REFERENCES \usepackage[minnames=1,maxnames=2,backend=bibtex]{biblatex} \AtEveryCitekey{\clearfield{url}} <>= pkgmaker::latex_bibliography('doRNG') @ \newcommand{\citet}[1]{\citeauthor{#1}~\cite{#1}} %% \newcommand{\graphwidth}{0.9\columnwidth} % clever references \usepackage[noabbrev, capitalise, nameinlink]{cleveref} \newcommand{\dorng}{\code{\%dorng\%}\xspace} \title{Using the \code{doRNG} package\\ {\small \Rpkg{doRNG} -- Version \Sexpr{packageVersion('doRNG')}}} \author{Renaud Gaujoux} \begin{document} \maketitle \tableofcontents \section*{Introduction} \addcontentsline{toc}{section}{Introduction} Research reproducibility is an issue of concern, e.g. in bioinformatics \cite{Hothorn2011,Stodden2011,Ioannidis2008}. Some analyses require multiple independent runs to be performed, or are amenable to a split-and-reduce scheme. For example, some optimisation algorithms are run multiple times from different random starting points, and the result that achieves the least approximation error is selected. The \citeCRANpkg{foreach} provides a very convenient way to perform parallel computations, with different parallel environments such as MPI or Redis, using a transparent loop-like syntax: <>= options(width=90) library(pkgmaker) library(knitr) opts_chunk$set(size = "footnotesize") knit_hooks$set(try = pkgmaker::hook_try) @ <>= # load and register parallel backend for multicore computations library(doParallel) cl <- makeCluster(2) registerDoParallel(cl) # perform 5 tasks in parallel x <- foreach(i=1:5) %dopar% { i + runif(1) } unlist(x) @ For each parallel environment a \emph{backend} is implemented as a specialised \code{\%dopar\%} operator, which performs the setup and pre/post-processing specifically required by the environment (e.g. export of variable to each worker). The \code{foreach} function and the \code{\%dopar\%} operator handle the generic parameter dispatch when the task are split between worker processes, as well as the reduce step -- when the results are returned to the master worker. When stochastic computations are involved, special random number generators must be used to ensure that the separate computations are indeed statistically independent -- unless otherwise wanted -- and that the loop is reproducible. In particular, standard \code{\%dopar\%} loops are not reproducible: <>= # with standard %dopar%: foreach loops are not reproducible set.seed(123) res <- foreach(i=1:5) %dopar% { runif(3) } set.seed(123) res2 <- foreach(i=1:5) %dopar% { runif(3) } identical(res, res2) @ A random number generator commonly used to achieve reproducibility is the combined multiple-recursive generator from \citet{Lecuyer1999}. This generator can generate independent random streams, from a 6-length numeric seed. The idea is then to generate a sequence of random stream of the same length as the number of iteration (i.e. tasks) and use a different stream when computing each one of them. The \citeCRANpkg{doRNG} provides convenient ways to implement reproducible parallel \code{foreach} loops, independently of the parallel backend used to perform the computation. We illustrate its use, showing how non-reproducible loops can be made reproducible, even when tasks are not scheduled in the same way in two separate set of runs, e.g. when the workers do not get to compute the same number of tasks or the number of workers is different. The package has been tested with the \CRANpkg*{doParallel} and \CRANpkg*{doMPI} packages \citepkg{Rpackage:doMPI,Rpackage:doParallel}, but should work with other backends such as provided by the \citeCRANpkg{doRedis}. \section{The \texttt{\%dorng\%} operator} The \Rpkg{doRNG} defines a new generic operator, \code{\%dorng\%}, to be used with foreach loops, instead of the standard {\%dopar\%}. Loops that use this operator are \emph{de facto} reproducible. <>= # load the doRNG package library(doRNG) # using %dorng%: loops _are_ reproducible set.seed(123) res <- foreach(i=1:5) %dorng% { runif(3) } set.seed(123) res2 <- foreach(i=1:5) %dorng% { runif(3) } identical(res, res2) @ \subsection{How it works} For a loop with $N$ iterations, the \code{\%dorng\%} operator internally performs the following tasks: \begin{enumerate} \item generate a sequence of random seeds $(S_i)_{1\leq i\leq N}$ for the \proglang{R} random number generator \code{"L'Ecuyer-CMRG"} \cite{Lecuyer1999}, using the function \code{nextRNGStream} from the \citeCRANpkg{parallel}, which ensure the different RNG streams are statistically independent; \item modify the loop's \proglang{R} expression so that the random number generator is set to \code{"L'Ecuyer-CMRG"} at the beginning of each iteration, and is seeded with consecutive seeds in $(S_n)$: iteration $i$ is seeded with $S_i$, $1\leq i\leq N$; \item call the standard \code{\%dopar\%} operator, which in turn calls the relevant (i.e. registered) foreach parallel backend; \item store the whole sequence of random seeds as an attribute in the result object: <>= attr(res, 'rng') @ \end{enumerate} \subsection{Seeding computations} Sequences of random streams for \code{"L'Ecuyer-CMRG"} are generated using a 6-length integer seed, e.g.,: <>= nextRNGStream(c(407L, 1:6)) @ However, the \code{\%dorng\%} operator provides alternative -- convenient -- ways of seeding reproducible loops. \begin{description} \item[\code{set.seed}:] as shown above, calling \code{set.seed} before the loop ensure reproducibility of the results, using a single integer as a seed. The actual 6-length seed is then generated with an internal call to \code{RNGkind("L'Ecuyer-CMRG")}. \item[\code{.options.RNG} with single integer:] the \dorng operator support options that can be passed in the \code{foreach} statement, containing arguments for the internal call to \code{set.seed}: <>= # use a single numeric as a seed s <- foreach(i=1:5, .options.RNG=123) %dorng% { runif(3) } s2 <- foreach(i=1:5, .options.RNG=123) %dorng% { runif(3) } identical(s, s2) @ \noindent \textbf{Note}: calling \code{set.seed} before the loop is equivalent to passing the seed in \code{.options.RNG}. See \cref{sec:set_seed} for more details. \medskip The kind of Normal generator may also be passed in \code{.options.RNG}: <>= ## Pass the Normal RNG kind to use within the loop # results are identical if not using the Normal kind in the loop optsN <- list(123, normal.kind="Ahrens") resN.U <- foreach(i=1:5, .options.RNG=optsN) %dorng% { runif(3) } identical(resN.U[1:5], res[1:5]) # Results are different if the Normal kind is used and is not the same resN <- foreach(i=1:5, .options.RNG=123) %dorng% { rnorm(3) } resN1 <- foreach(i=1:5, .options.RNG=optsN) %dorng% { rnorm(3) } resN2 <- foreach(i=1:5, .options.RNG=optsN) %dorng% { rnorm(3) } identical(resN[1:5], resN1[1:5]) identical(resN1[1:5], resN2[1:5]) @ \item[\code{.options.RNG} with 6-length:] the actual 6-length integer seed used for the first RNG stream may be passed via \code{options.RNG}: <>= # use a 6-length numeric s <- foreach(i=1:5, .options.RNG=1:6) %dorng% { runif(3) } attr(s, 'rng')[1:3] @ \item[\code{.options.RNG} with 7-length:] a 7-length integer seed may also be passed via \code{options.RNG}, which is useful to seed a loop with the value of \code{.Random.seed} as used in some iteration of another loop\footnote{Note that the RNG kind is then always required to be the \code{"L'Ecuyer-CMRG"}, i.e. the first element of the seed must have unit 7 (e.g. 407 or 107).}: <>= # use a 7-length numeric, used as first value for .Random.seed seed <- attr(res, 'rng')[[2]] s <- foreach(i=1:5, .options.RNG=seed) %dorng% { runif(3) } identical(s[1:4], res[2:5]) @ \item[\code{.options.RNG} with complete sequence of seeds:] the complete description of the sequence of seeds to be used may be passed via \code{options.RNG}, as a list or a matrix with the seeds in columns. This is useful to seed a loop exactly as desired, e.g. using an RNG other than \code{"L'Ecuyer-CMRG"}, or using different RNG kinds in each iteration, which probably have different seed length, in order to compare their stochastic properties. It also allows to reproduce \code{\%dorng\%} loops without knowing their seeding details: <>= # reproduce previous %dorng% loop s <- foreach(i=1:5, .options.RNG=res) %dorng% { runif(3) } identical(s, res) ## use completely custom sequence of seeds (e.g. using RNG "Marsaglia-Multicarry") # as a matrix seedM <- rbind(rep(401, 5), mapply(rep, 1:5, 2)) seedM sM <- foreach(i=1:5, .options.RNG=seedM) %dorng% { runif(3) } # same seeds passed as a list seedL <- lapply(seq(ncol(seedM)), function(i) seedM[,i]) sL <- foreach(i=1:5, .options.RNG=seedL) %dorng% { runif(3) } identical(sL, sM) @ \end{description} \subsection{Difference between \texttt{set.seed} and \texttt{.options.RNG}} \label{sec:set_seed} While it is equivalent to seed \dorng loops with \code{set.seed} and \code{.options.RNG}, it is important to note that the result depends on the current RNG kind \footnote{See \cref{sec:issues} about a bug in versions < 1.4 on this feature.}: <>= # default RNG kind RNGkind('default') def <- foreach(i=1:5, .options.RNG=123) %dorng% { runif(3) } # Marsaglia-Multicarry RNGkind('Marsaglia') mars <- foreach(i=1:5, .options.RNG=123) %dorng% { runif(3) } identical(def, mars) # revert to default RNG kind RNGkind('default') @ This is a ``normal'' behaviour, which is a side-effect of the expected equivalence between \code{set.seed} and \code{.options.RNG}. This should not be a problem for reproducibility though, as R RNGs are stable across versions, and loops are most of the time used with the default RNG settings. In order to ensure seeding is independent from the current RNG, one has to pass a 7-length numeric seed to \code{.options.RNG}, which is then used directly as a value for \code{.Random.seed} (see below). \section{Parallel environment independence} An important feature of \code{\%dorng\%} loops is that their result is independent of the underlying parallel physical settings. Two separate runs seeded with the same value will always produce the same results. Whether they use the same number of worker processes, parallel backend or task scheduling does not influence the final result. This also applies to computations performed sequentially with the \code{doSEQ} backend. The following code illustrates this feature using 2 or 3 workers. <>= # define a stochastic task to perform task <- function() c(pid=Sys.getpid(), val=runif(1)) # using the previously registered cluster with 2 workers set.seed(123) res_2workers <- foreach(i=1:5, .combine=rbind) %dorng% { task() } # stop cluster stopCluster(cl) # Sequential computation registerDoSEQ() set.seed(123) res_seq <- foreach(i=1:5, .combine=rbind) %dorng% { task() } # # Using 3 workers # NB: if re-running this vignette you should edit to force using 3 here cl <- makeCluster( if(isManualVignette()) 3 else 2) length(cl) # register new cluster registerDoParallel(cl) set.seed(123) res_3workers <- foreach(i=1:5, .combine=rbind) %dorng% { task() } # task schedule is different pid <- rbind(res1=res_seq[,1], res_2workers[,1], res2=res_3workers[,1]) storage.mode(pid) <- 'integer' pid # results are identical identical(res_seq[,2], res_2workers[,2]) && identical(res_2workers[,2], res_3workers[,2]) @ \section{Reproducible \texttt{\%dopar\%} loops} The \Rpkg{doRNG} also provides a non-invasive way to convert \code{\%dopar\%} loops into reproducible loops, i.e. without changing their actual definition. It is useful to quickly ensure the reproducibility of existing code or functions whose definition is not accessible (e.g. from other packages). This is achieved by registering the \code{doRNG} backend: <>= set.seed(123) res <- foreach(i=1:5) %dorng% { runif(3) } registerDoRNG(123) res_dopar <- foreach(i=1:5) %dopar% { runif(3) } identical(res_dopar, res) attr(res_dopar, 'rng') @ \section{Reproducibile sets of loops} Sequences of multiple loops are reproducible, whether using the \code{\%dorng\%} operator or the registered \code{doRNG} backend: <>= set.seed(456) s1 <- foreach(i=1:5) %dorng% { runif(3) } s2 <- foreach(i=1:5) %dorng% { runif(3) } # the two loops do not use the same streams: different results identical(s1, s2) # but the sequence of loops is reproducible as a whole set.seed(456) r1 <- foreach(i=1:5) %dorng% { runif(3) } r2 <- foreach(i=1:5) %dorng% { runif(3) } identical(r1, s1) && identical(r2, s2) # one can equivalently register the doRNG backend and use %dopar% registerDoRNG(456) r1 <- foreach(i=1:5) %dopar% { runif(3) } r2 <- foreach(i=1:5) %dopar% { runif(3) } identical(r1, s1) && identical(r2, s2) @ \section{Nested and conditional loops} \label{sec:nested} Nested and conditional foreach loops are currently not supported and generate an error: <>= # nested loop try( foreach(i=1:10) %:% foreach(j=1:i) %dorng% { rnorm(1) } ) # conditional loop try( foreach(i=1:10) %:% when(i %% 2 == 0) %dorng% { rnorm(1) } ) @ In this section, we propose a general work around for this kind of loops, that will eventually be incorporated in the \code{\%dorng\%} operator -- when I find out how to mimic its behaviour from the operator itself. \subsection{Nested loops} The idea is to create a sequence of RNG seeds before the outer loop, and use each of them successively to set the RNG in the inner loop -- which is exactly what \code{\%dorng\%} does for simple loops: <>= # doRNG must not be registered registerDoParallel(cl) # generate sequence of seeds of length the number of computations n <- 10; p <- 5 rng <- RNGseq( n * p, 1234) # run standard nested foreach loop res <- foreach(i=1:n) %:% foreach(j=1:p, r=rng[(i-1)*p + 1:p]) %dopar% { # set RNG seed rngtools::setRNG(r) # do your own computation ... c(i, j, rnorm(1)) } # Compare against the equivalent sequential computations k <- 1 res2 <- foreach(i=1:n) %:% foreach(j=1:p) %do%{ # set seed rngtools::setRNG(rng[[k]]) k <- k + 1 # do your own computation ... c(i, j, rnorm(1)) } stopifnot( identical(res, res2) ) @ The following is a more complex example with unequal -- but \textbf{known \emph{a priori}} -- numbers of iterations performed in the inner loops: <>= # generate sequence of seeds of length the number of computations n <- 10 rng <- RNGseq( n * (n+1) / 2, 1234) # run standard nested foreach loop res <- foreach(i=1:n) %:% foreach(j=1:i, r=rng[(i-1)*i/2 + 1:i]) %dopar%{ # set RNG seed rngtools::setRNG(r) # do your own computation ... c(i, j, rnorm(1)) } # Compare against the equivalent sequential computations k <- 1 res2 <- foreach(i=1:n) %:% foreach(j=1:i) %do%{ # set seed rngtools::setRNG(rng[[k]]) k <- k + 1 # do your own computation ... c(i, j, rnorm(1)) } stopifnot( identical(res, res2) ) @ \subsection{Conditional loops} The work around used for nested loops applies to conditional loops that use the \code{when()} clause. It ensures that the RNG seed use for a given inner iteration does not depend on the filter, but only on its index in the unconditional-unfolded loop: <>= # un-conditional single loop resAll <- foreach(i=1:n, .options.RNG=1234) %dorng%{ # do your own computation ... c(i, rnorm(1)) } # generate sequence of RNG rng <- RNGseq(n, 1234) # conditional loop: even iterations resEven <- foreach(i=1:n, r=rng) %:% when(i %% 2 == 0) %dopar%{ # set RNG seed rngtools::setRNG(r) # do your own computation ... c(i, rnorm(1)) } # conditional loop: odd iterations resOdd <- foreach(i=1:n, r=rng) %:% when(i %% 2 == 1) %dopar%{ # set RNG seed rngtools::setRNG(r) # do your own computation ... c(i, rnorm(1)) } # conditional loop: only first 2 and last 2 resFL <- foreach(i=1:n, r=rng) %:% when(i %in% c(1,2,n-1,n)) %dopar%{ # set RNG seed rngtools::setRNG(r) # do your own computation ... c(i, rnorm(1)) } # compare results stopifnot( identical(resAll[seq(2,n,by=2)], resEven) ) stopifnot( identical(resAll[seq(1,n,by=2)], resOdd) ) stopifnot( identical(resAll[c(1,2,n-1,n)], resFL) ) @ \subsection{Nested conditional loops} Conditional nested loops may use the same work around, as shown in this intricate example: <>= # generate sequence of seeds of length the number of computations n <- 10 rng <- RNGseq( n * (n+1) / 2, 1234) # run standard nested foreach loop res <- foreach(i=1:n) %:% when(i %% 2 == 0) %:% foreach(j=1:i, r=rng[(i-1)*i/2 + 1:i]) %dopar%{ # set RNG seed rngtools::setRNG(r) # do your own computation ... c(i, j, rnorm(1)) } # Compare against the equivalent sequential computations k <- 1 resAll <- foreach(i=1:n) %:% foreach(j=1:i) %do%{ # set seed rngtools::setRNG(rng[[k]]) k <- k + 1 # do your own computation ... c(i, j, rnorm(1)) } stopifnot( identical(resAll[seq(2,n,by=2)], res) ) @ \section{Performance overhead} The extra setup performed by the \code{\%dorng\%} operator leads to a slight performance over-head, which might be significant for very quick computations, but should not be a problem for realistic computations. The benchmarks below show that a \code{\%dorng\%} loop may take up to two seconds more than the equivalent \code{\%dopar\%} loop, which is not significant in practice, where parallelised computations typically take several minutes. <>= # load rbenchmark library(rbenchmark) # comparison is done on sequential computations registerDoSEQ() rPar <- function(n, s=0){ foreach(i=1:n) %dopar% { Sys.sleep(s) } } rRNG <- function(n, s=0){ foreach(i=1:n) %dorng% { Sys.sleep(s) } } # run benchmark cmp <- benchmark(rPar(10), rRNG(10) , rPar(25), rRNG(25) , rPar(50), rRNG(50) , rPar(50, .01), rRNG(50, .01) , rPar(10, .05), rRNG(10, .05) , replications=5) # order by increasing elapsed time cmp[order(cmp$elapsed), ] @ \section{Known issues} \label{sec:issues} \begin{itemize} \item Nested and/or conditional foreach loops using the operator \code{\%:\%} are not currently not supported (see \cref{sec:nested} for a work around). \item An error is thrown in \code{doRNG} 1.2.6, when the package \code{iterators} was not loaded, when used with \code{foreach} >= 1.4. \item There was a bug in versions prior to \code{1.4}, which caused \code{set.seed} and \code{.options.RNG} not to be equivalent when the current RNG was \code{"L'Ecuyer-CMRG"}. This behaviour can still be reproduced by setting: <>= doRNGversion('1.3') @ To revert to the latest default behaviour: <>= doRNGversion(NULL) @ \end{itemize} \section{News and changes} {\scriptsize \begin{verbatim} <>= cat(paste(readLines(system.file('NEWS', package='doRNG')), collapse="\n")) @ \end{verbatim} } \section*{Cleanup} <>= stopCluster(cl) @ \section*{Session information} \addcontentsline{toc}{section}{Session information} <>= sessionInfo() @ \printbibliography[heading=bibintoc] \end{document} doRNG/inst/doc/doRNG.R0000644000176200001440000002436313613333410014046 0ustar liggesusers## ----pkgmaker_preamble, echo=FALSE, results='asis'---------------------------- pkgmaker::latex_preamble() ## ----bibliofile, echo=FALSE, results='asis'----------------------------------- pkgmaker::latex_bibliography('doRNG') ## ----init, include = FALSE-------------------------------------------------------------- options(width=90) library(pkgmaker) library(knitr) opts_chunk$set(size = "footnotesize") knit_hooks$set(try = pkgmaker::hook_try) ## ----foreach---------------------------------------------------------------------------- # load and register parallel backend for multicore computations library(doParallel) cl <- makeCluster(2) registerDoParallel(cl) # perform 5 tasks in parallel x <- foreach(i=1:5) %dopar% { i + runif(1) } unlist(x) ## ----dopar, tidy=FALSE------------------------------------------------------------------ # with standard %dopar%: foreach loops are not reproducible set.seed(123) res <- foreach(i=1:5) %dopar% { runif(3) } set.seed(123) res2 <- foreach(i=1:5) %dopar% { runif(3) } identical(res, res2) ## ----dorng, tidy=FALSE------------------------------------------------------------------ # load the doRNG package library(doRNG) # using %dorng%: loops _are_ reproducible set.seed(123) res <- foreach(i=1:5) %dorng% { runif(3) } set.seed(123) res2 <- foreach(i=1:5) %dorng% { runif(3) } identical(res, res2) ## ----attr------------------------------------------------------------------------------- attr(res, 'rng') ## ----nextRNGstream---------------------------------------------------------------------- nextRNGStream(c(407L, 1:6)) ## ----options_single--------------------------------------------------------------------- # use a single numeric as a seed s <- foreach(i=1:5, .options.RNG=123) %dorng% { runif(3) } s2 <- foreach(i=1:5, .options.RNG=123) %dorng% { runif(3) } identical(s, s2) ## ----options_single_normalkind---------------------------------------------------------- ## Pass the Normal RNG kind to use within the loop # results are identical if not using the Normal kind in the loop optsN <- list(123, normal.kind="Ahrens") resN.U <- foreach(i=1:5, .options.RNG=optsN) %dorng% { runif(3) } identical(resN.U[1:5], res[1:5]) # Results are different if the Normal kind is used and is not the same resN <- foreach(i=1:5, .options.RNG=123) %dorng% { rnorm(3) } resN1 <- foreach(i=1:5, .options.RNG=optsN) %dorng% { rnorm(3) } resN2 <- foreach(i=1:5, .options.RNG=optsN) %dorng% { rnorm(3) } identical(resN[1:5], resN1[1:5]) identical(resN1[1:5], resN2[1:5]) ## ----options_6length-------------------------------------------------------------------- # use a 6-length numeric s <- foreach(i=1:5, .options.RNG=1:6) %dorng% { runif(3) } attr(s, 'rng')[1:3] ## ----options_7length-------------------------------------------------------------------- # use a 7-length numeric, used as first value for .Random.seed seed <- attr(res, 'rng')[[2]] s <- foreach(i=1:5, .options.RNG=seed) %dorng% { runif(3) } identical(s[1:4], res[2:5]) ## ----options_list----------------------------------------------------------------------- # reproduce previous %dorng% loop s <- foreach(i=1:5, .options.RNG=res) %dorng% { runif(3) } identical(s, res) ## use completely custom sequence of seeds (e.g. using RNG "Marsaglia-Multicarry") # as a matrix seedM <- rbind(rep(401, 5), mapply(rep, 1:5, 2)) seedM sM <- foreach(i=1:5, .options.RNG=seedM) %dorng% { runif(3) } # same seeds passed as a list seedL <- lapply(seq(ncol(seedM)), function(i) seedM[,i]) sL <- foreach(i=1:5, .options.RNG=seedL) %dorng% { runif(3) } identical(sL, sM) ## ----set_seed_diff---------------------------------------------------------------------- # default RNG kind RNGkind('default') def <- foreach(i=1:5, .options.RNG=123) %dorng% { runif(3) } # Marsaglia-Multicarry RNGkind('Marsaglia') mars <- foreach(i=1:5, .options.RNG=123) %dorng% { runif(3) } identical(def, mars) # revert to default RNG kind RNGkind('default') ## ----schedule, tidy=FALSE--------------------------------------------------------------- # define a stochastic task to perform task <- function() c(pid=Sys.getpid(), val=runif(1)) # using the previously registered cluster with 2 workers set.seed(123) res_2workers <- foreach(i=1:5, .combine=rbind) %dorng% { task() } # stop cluster stopCluster(cl) # Sequential computation registerDoSEQ() set.seed(123) res_seq <- foreach(i=1:5, .combine=rbind) %dorng% { task() } # # Using 3 workers # NB: if re-running this vignette you should edit to force using 3 here cl <- makeCluster( if(isManualVignette()) 3 else 2) length(cl) # register new cluster registerDoParallel(cl) set.seed(123) res_3workers <- foreach(i=1:5, .combine=rbind) %dorng% { task() } # task schedule is different pid <- rbind(res1=res_seq[,1], res_2workers[,1], res2=res_3workers[,1]) storage.mode(pid) <- 'integer' pid # results are identical identical(res_seq[,2], res_2workers[,2]) && identical(res_2workers[,2], res_3workers[,2]) ## ----registerDoRNG---------------------------------------------------------------------- set.seed(123) res <- foreach(i=1:5) %dorng% { runif(3) } registerDoRNG(123) res_dopar <- foreach(i=1:5) %dopar% { runif(3) } identical(res_dopar, res) attr(res_dopar, 'rng') ## ----multiple, tidy=FALSE--------------------------------------------------------------- set.seed(456) s1 <- foreach(i=1:5) %dorng% { runif(3) } s2 <- foreach(i=1:5) %dorng% { runif(3) } # the two loops do not use the same streams: different results identical(s1, s2) # but the sequence of loops is reproducible as a whole set.seed(456) r1 <- foreach(i=1:5) %dorng% { runif(3) } r2 <- foreach(i=1:5) %dorng% { runif(3) } identical(r1, s1) && identical(r2, s2) # one can equivalently register the doRNG backend and use %dopar% registerDoRNG(456) r1 <- foreach(i=1:5) %dopar% { runif(3) } r2 <- foreach(i=1:5) %dopar% { runif(3) } identical(r1, s1) && identical(r2, s2) ## ----nested_error, error = TRUE, try = TRUE--------------------------------------------- # nested loop try( foreach(i=1:10) %:% foreach(j=1:i) %dorng% { rnorm(1) } ) # conditional loop try( foreach(i=1:10) %:% when(i %% 2 == 0) %dorng% { rnorm(1) } ) ## ----nested----------------------------------------------------------------------------- # doRNG must not be registered registerDoParallel(cl) # generate sequence of seeds of length the number of computations n <- 10; p <- 5 rng <- RNGseq( n * p, 1234) # run standard nested foreach loop res <- foreach(i=1:n) %:% foreach(j=1:p, r=rng[(i-1)*p + 1:p]) %dopar% { # set RNG seed rngtools::setRNG(r) # do your own computation ... c(i, j, rnorm(1)) } # Compare against the equivalent sequential computations k <- 1 res2 <- foreach(i=1:n) %:% foreach(j=1:p) %do%{ # set seed rngtools::setRNG(rng[[k]]) k <- k + 1 # do your own computation ... c(i, j, rnorm(1)) } stopifnot( identical(res, res2) ) ## ----nested_unequal--------------------------------------------------------------------- # generate sequence of seeds of length the number of computations n <- 10 rng <- RNGseq( n * (n+1) / 2, 1234) # run standard nested foreach loop res <- foreach(i=1:n) %:% foreach(j=1:i, r=rng[(i-1)*i/2 + 1:i]) %dopar%{ # set RNG seed rngtools::setRNG(r) # do your own computation ... c(i, j, rnorm(1)) } # Compare against the equivalent sequential computations k <- 1 res2 <- foreach(i=1:n) %:% foreach(j=1:i) %do%{ # set seed rngtools::setRNG(rng[[k]]) k <- k + 1 # do your own computation ... c(i, j, rnorm(1)) } stopifnot( identical(res, res2) ) ## ----conditional------------------------------------------------------------------------ # un-conditional single loop resAll <- foreach(i=1:n, .options.RNG=1234) %dorng%{ # do your own computation ... c(i, rnorm(1)) } # generate sequence of RNG rng <- RNGseq(n, 1234) # conditional loop: even iterations resEven <- foreach(i=1:n, r=rng) %:% when(i %% 2 == 0) %dopar%{ # set RNG seed rngtools::setRNG(r) # do your own computation ... c(i, rnorm(1)) } # conditional loop: odd iterations resOdd <- foreach(i=1:n, r=rng) %:% when(i %% 2 == 1) %dopar%{ # set RNG seed rngtools::setRNG(r) # do your own computation ... c(i, rnorm(1)) } # conditional loop: only first 2 and last 2 resFL <- foreach(i=1:n, r=rng) %:% when(i %in% c(1,2,n-1,n)) %dopar%{ # set RNG seed rngtools::setRNG(r) # do your own computation ... c(i, rnorm(1)) } # compare results stopifnot( identical(resAll[seq(2,n,by=2)], resEven) ) stopifnot( identical(resAll[seq(1,n,by=2)], resOdd) ) stopifnot( identical(resAll[c(1,2,n-1,n)], resFL) ) ## ----nested_conditional----------------------------------------------------------------- # generate sequence of seeds of length the number of computations n <- 10 rng <- RNGseq( n * (n+1) / 2, 1234) # run standard nested foreach loop res <- foreach(i=1:n) %:% when(i %% 2 == 0) %:% foreach(j=1:i, r=rng[(i-1)*i/2 + 1:i]) %dopar%{ # set RNG seed rngtools::setRNG(r) # do your own computation ... c(i, j, rnorm(1)) } # Compare against the equivalent sequential computations k <- 1 resAll <- foreach(i=1:n) %:% foreach(j=1:i) %do%{ # set seed rngtools::setRNG(rng[[k]]) k <- k + 1 # do your own computation ... c(i, j, rnorm(1)) } stopifnot( identical(resAll[seq(2,n,by=2)], res) ) ## ----perf, cache=TRUE------------------------------------------------------------------- # load rbenchmark library(rbenchmark) # comparison is done on sequential computations registerDoSEQ() rPar <- function(n, s=0){ foreach(i=1:n) %dopar% { Sys.sleep(s) } } rRNG <- function(n, s=0){ foreach(i=1:n) %dorng% { Sys.sleep(s) } } # run benchmark cmp <- benchmark(rPar(10), rRNG(10) , rPar(25), rRNG(25) , rPar(50), rRNG(50) , rPar(50, .01), rRNG(50, .01) , rPar(10, .05), rRNG(10, .05) , replications=5) # order by increasing elapsed time cmp[order(cmp$elapsed), ] ## ----doRNGversion----------------------------------------------------------------------- doRNGversion('1.3') ## ----doRNGversion_revert---------------------------------------------------------------- doRNGversion(NULL) ## ----news, echo=FALSE, results='asis'--------------------------------------------------- cat(paste(readLines(system.file('NEWS', package='doRNG')), collapse="\n")) ## ----stopCluster------------------------------------------------------------------------ stopCluster(cl) ## ----session_info, echo=FALSE, comment=NA----------------------------------------------- sessionInfo()