latte/0000755000176200001440000000000015021467402011364 5ustar liggesuserslatte/MD50000644000176200001440000000421515021467402011676 0ustar liggesusers0566cf8f08bf02e4575dd056f4e9ae6b *DESCRIPTION 9cffd53912d9ce41beae80172639d991 *NAMESPACE 99b8d224683609dec83d15237349f60d *NEWS a17eb6569801a18b9feaf0a59653de07 *R/attach.R 920cfb189e327cd47fe6e267351e6ce8 *R/call-latte.R 9676d89ce22582d7b559f3591471696a *R/genmodel.R a2d82d7c949847c1dddbd7d41a119372 *R/helpers.R ae4c62c444d9a1c213a057a1e21afd28 *R/kprod.R 790e3da5f9294077b0cc31e9f4b673c1 *R/latte-count.R 6e760af2eddc2dffc239ed1273751224 *R/latte-files.R 5a4b66ad973c945ac495443e7ac36bba *R/latte-optim.R 2fb9a3e0d7e28e015e64da92286cc42d *R/latte-package.R 76fa32c5a71c974a2259809f61b8cfdd *R/lattice-bases.R 30279d8f4d4659552c166341cab7ebd6 *R/ones.R b6c46e86620212e98499aed55923f0b5 *R/plot-matrix.R 75ef61f5cc86d7a85408fdaa37bdcaf6 *R/ppi.R 73ec904d73065e8e7072b48570e64c24 *R/qsolve.R cbad0f4f6f6936735a705a97f25c1e9b *R/set-paths.R 7bd608b10db8fc9821208429090ed78f *R/tab2vec.R 6cfc208381df076bb44bdcaeac1435fc *R/tableau.R 20c096a4357ce9b7a5923dd421bc3aa6 *R/vec2tab.R 9b2a0ceaf3afcedee53b02d782018fa0 *R/zsolve.R 840049371aa90a71d42ebd6ba78d007f *inst/CITATION 620ca6100d9b94c167c6791db495b24a *inst/INSTALL.txt 32b9477248a45342f48c665ad8faea95 *man/call_latte.Rd b77060865100445898772c22b5a9633a *man/genmodel.Rd 5a99d07e35e9913a9f26ad70b509962b *man/kprod.Rd 4d83d8218cc0fde678e2fb51f96d06aa *man/latte-count.Rd 64c83cc21f5a3f3713313b2403b5f629 *man/latte-files.Rd fdd52c6231e156ae2fee771a431a0d26 *man/latte-optim.Rd 6fba882489836d76dd80cfcfaae1f6b1 *man/latte.Rd e0e696ee0f179ba1afe45609421acac1 *man/lattice-bases.Rd cac090aa1766d05bd4092175f850fd75 *man/ones.Rd dc3f019241455200822f7fd9127899c5 *man/pathing.Rd 0f0bba08d9dc44f1436cbbdbca8146c5 *man/plot-matrix.Rd 0b3f9f4f5de07aa5fef4dded810d7c0b *man/ppi.Rd 4670f9697efc47c094a7722ff2b38d31 *man/print.tableau.Rd fe7d9175ef697dbfdf44d4525e8f01e7 *man/qsolve.Rd eb0c6cb22427bf13552b77c9a0ee1835 *man/reexports.Rd 6473b54ad4f8f1cdd73b390858a88496 *man/tab2vec.Rd d9c241780816f9b5a2f37719fd58f3a1 *man/tableau.Rd d6e4f55df52815b09ddb1a54334a5c64 *man/vec2tab.Rd 3b8e64c0c422733aa5046b4928ec4aab *man/zsolve.Rd c135e7309b37186504957f66ba3b7fd3 *tools/countExample-1.png e1e5cb41c03b50e17ccae5d18503821b *tools/ipCheck-1.png latte/R/0000755000176200001440000000000014774756512011606 5ustar liggesuserslatte/R/latte-count.R0000644000176200001440000002512615007143646014162 0ustar liggesusers#' Count integer points in a polytope #' #' \code{latte_count} uses LattE's count function to count the (integer) lattice #' points in a polytope and compute Ehrhart polynomials. #' #' The specification should be one of the following: (1) a character string or #' strings containing an inequality in the mpoly expression format (see #' examples), (2) a list of vertices, (3) a list of A and b for the equation Ax #' <= b (see examples), or (4) raw code for LattE's count program. If a #' character vector is supplied, (1) and (4) are distinguished by the number of #' strings. #' #' Behind the scenes, count works by writing a latte file and running count on #' it. If a specification other than a length one character is given to it #' (which is considered to be the code), count attempts to convert it into LattE #' code and then run count on it. #' #' @param spec Specification, see details and examples #' @param dir Directory to place the files in, without an ending / #' @param quiet Show latte output? #' @param mpoly When opts = "--ehrhart-polynomial", return the mpoly version of #' it #' @param ... Additional arguments to pass to the function, see count --help at #' the command line to see examples. Note that dashes - should be specified #' with underscores _ #' @return The count. If the count is a number has less than 10 digits, an #' integer is returned. If the number has 10 or more digits, an integer in a #' character string is returned. You may want to use the gmp package's as.bigz #' to parse it. #' @name latte-count #' @examples #' #' if (has_latte()) { #' #' spec <- c("x + y <= 10", "x >= 1", "y >= 1") #' latte_count(spec) # 45 #' latte_count(spec, quiet = FALSE) # 45 #' latte_count(spec, dilation = 10) # 3321 #' latte_count(spec, homog = TRUE) # 45 #' #' # by default, the output from LattE is in #' list.files(tempdir()) #' list.files(tempdir(), recursive = TRUE) #' #' # ehrhart polynomials #' latte_count(spec, ehrhart_polynomial = TRUE) #' latte_count(spec, ehrhart_polynomial = TRUE, mpoly = FALSE) #' #' # ehrhart series (raw since mpoly can't handle rational functions) #' latte_count(spec, ehrhart_series = TRUE) #' #' # simplified ehrhart series - not yet implemented #' #latte_count(spec, simplified_ehrhart_polynomial = TRUE) #' #' # first terms of the ehrhart series #' latte_count(spec, ehrhart_taylor = 1) #' # latte_count(spec, ehrhart_taylor = 2) #' # latte_count(spec, ehrhart_taylor = 3) #' # latte_count(spec, ehrhart_taylor = 4) #' #' # multivariate generating function #' latte_count(spec, multivariate_generating_function = TRUE) #' #' #' # by vertices #' spec <- list(c(1,1), c(10,1), c(1,10), c(10,10)) #' latte_count(spec) #' latte_count(spec, vrep = TRUE) #' #' code <- " #' 5 3 #' 1 -1 0 #' 1 0 -1 #' 1 -1 -1 #' 0 1 0 #' 0 0 1 #' " #' latte_count(code) #' #' #' # for Ax <= b, see this example from the latte manual p.10 #' A <- matrix(c( #' 1, 0, #' 0, 1, #' 1, 1, #' -1, 0, #' 0, -1 #' ), nrow = 5, byrow = TRUE) #' b <- c(1, 1, 1, 0, 0) #' latte_count(list(A = A, b = b)) #' #' #' #' #' #' #' #' #' #' } #' #' count_core <- function(spec, dir = tempdir(), quiet = TRUE, mpoly = TRUE, ...){ if (!has_latte()) missing_latte_stop() ## initialize specification specification <- "unknown" ## compute other args opts <- as.list(match.call(expand.dots = FALSE))[["..."]] if (is.null(opts)) opts <- list() ## look at opts if (("erhart_series" %in% names(opts)) && mpoly) { message("mpoly can't handle rational functions; reverting to raw output.") mpoly <- FALSE } if ("simplified_ehrhart_polynomial" %in% names(opts)) { stop("This option is not yet supported by latte.", call. = FALSE) } ## if the specification is pure code if(is.character(spec) && length(spec) == 1L){ specification <- "code" code <- spec } ## if the specification is A and b if(is.list(spec) && length(spec) == 2L){ bNegA <- unname(cbind(spec$b, -spec$A)) spec <- paste(dim(bNegA), collapse = " ") bNegA <- paste(apply(bNegA, 1, paste, collapse = " "), collapse = "\n") spec <- paste(spec, bNegA, sep = "\n") spec <- str_c("\n", spec) specification <- "code" code <- spec } ## check for vertex specification if(("vrep" %in% names(opts)) && isTRUE(opts[["vrep"]])) specification <- "vertex" if( is.list(spec) && !is.mpolyList(spec) && (("vrep" %notin% names(opts)) || !isTRUE(opts[["vrep"]])) ){ specification <- "vertex" message("Undeclared vertex specification, setting vrep = TRUE.") opts <- c(opts, "vrep" = TRUE) } ## if giving a character string of equations, parse ## each to the poly <= 0 format # this should transition to eq_to_mp if (is.character(spec) && length(spec) > 1) { parsedSpec <- as.list(rep(NA, length(spec))) geqNdcs <- which(str_detect(spec, " >= ")) leqNdcs <- which(str_detect(spec, " <= ")) eeqNdcs <- which(str_detect(spec, " == ")) eqNdcs <- which(str_detect(spec, " = ")) if (length(geqNdcs) > 0) { tmp <- strsplit(spec[geqNdcs], " >= ") parsedSpec[geqNdcs] <- lapply(tmp, function(v) mp(v[2]) - mp(v[1])) } if (length(leqNdcs) > 0) { tmp <- strsplit(spec[leqNdcs], " <= ") parsedSpec[leqNdcs] <- lapply(tmp, function(v) mp(v[1]) - mp(v[2])) } if (length(eeqNdcs) > 0) { tmp <- strsplit(spec[eeqNdcs], " == ") parsedSpec[eeqNdcs] <- lapply(tmp, function(v) mp(v[1]) - mp(v[2])) } if (length(eqNdcs) > 0) { tmp <- strsplit(spec[eqNdcs], " = ") parsedSpec[eqNdcs] <- lapply(tmp, function(v) mp(v[1]) - mp(v[2])) } linearityNdcs <- sort(c(eeqNdcs, eqNdcs)) spec <- parsedSpec class(spec) <- "mpolyList" } ## convert the mpoly specification into a matrix, see latte manual, p. 8 if (is.mpolyList(spec)) { specification <- "hyperplane" if (!all(is.linear(spec))) stop("All polynomials must be linear.", call. = FALSE) mat <- mpoly_list_to_mat(spec) mat <- cbind(-mat[,"coef",drop=FALSE], -mat[,-ncol(mat)]) # convert to code code <- paste(nrow(mat), ncol(mat)) code <- str_c(code, "\n") code <- str_c(code, paste(apply(unname(mat), 1, paste, collapse = " "), collapse = "\n") ) if(length(linearityNdcs) > 0){ code <- str_c(code, "\n") code <- str_c(code, str_c("linearity ", length(linearityNdcs), " ", paste(linearityNdcs, collapse = " ")) ) } } ## convert vertex specification into a matrix if(specification == "vertex"){ if(any(!sapply(spec, function(v) length(v) != 1))){ stop("Unequal number of coordinates in vertex specification.", call. = FALSE) } mat <- matrix(unlist(spec), ncol = 2, byrow = TRUE) # convert to code mat <- cbind(1, mat) code <- paste(nrow(mat), ncol(mat)) code <- str_c(code, "\n") code <- str_c(code, paste(apply(unname(mat), 1, paste, collapse = " "), collapse = "\n") ) } ## make dir to put latte files in (within the tempdir) timestamped dir.create(project_dir <- file.path(dir, time_stamp())) ## write code file writeLines(code, con = file.path(project_dir, "count_code.latte")) ## switch to temporary directory user_working_directory <- getwd() setwd(project_dir); on.exit(setwd(user_working_directory), add = TRUE) ## run count call_latte("count", "count_code.latte", project_dir, opts) ## print count output when quiet = FALSE if(!quiet) cat(readLines("stdout"), sep = "\n") # note: strangely, latte posts non-error info to stderr if(!quiet) std_err <- readLines("stderr") if(!quiet && any(std_err != "")) message(str_c(std_err, collapse = "\n")) ## parse ehrhart polynomial if ( ("ehrhart_polynomial" %in% names(opts)) && isTRUE(opts[["ehrhart_polynomial"]]) ) { outPrint <- readLines("stdout") rawPoly <- rev(outPrint)[2] if(!mpoly) return(str_trim(rawPoly)) rawPoly <- str_replace_all(rawPoly, " \\* ", " ") if(str_sub(rawPoly, 1, 5) == " + 1 ") rawPoly <- str_sub(rawPoly, 6) return(mp(str_trim(rawPoly))) } ## parse ehrhart series if ( ("ehrhart_series" %in% names(opts)) && isTRUE(opts[["ehrhart_series"]]) ) { outPrint <- readLines("count_code.latte.rat") # take off initial "x := " and terminating ":" outPrint <- str_sub(outPrint, start = 6, end = nchar(outPrint)-1) # return return(outPrint) } ## parse multivariate generating function if ( ("multivariate_generating_function" %in% names(opts)) && isTRUE(opts[["multivariate_generating_function"]]) ) { outPrint <- readLines("count_code.latte.rat") # collapse outPrint <- paste(outPrint, collapse = "") # return if(!mpoly) return(outPrint) # change x[0] to vars[1], and so on indets <- vars(spec) for(k in 1:length(indets)){ outPrint <- str_replace_all(outPrint, str_c("x\\[",k-1,"\\]"), indets[k]) } return(outPrint) } ## parse truncated taylor series if ( ("ehrhart_taylor" %in% names(opts)) && isTRUE(opts[["ehrhart_taylor"]]) ) { outPrint <- readLines("stdout") # collapse outPrint <- paste(outPrint, collapse = " + ") outPrint <- str_replace_all(outPrint, "t", " t") # return if(!mpoly) return(outPrint) return(mp(outPrint)) } ## read in integer and parse if small enough out <- readLines("numOfLatticePoints") if(nchar(out) < 10) out <- as.integer(out) ## print out stats if(!quiet){ cat(readLines("latte_stats"), sep = "\n") cat("\n") } ## out out } #' @export #' @rdname latte-count latte_count <- memoise::memoise(count_core) #' @export #' @rdname latte-count latte_fcount <- count_core mpoly_list_to_mat <- function(mpolyList){ # this only works for linear mpolyList objects vars <- vars(mpolyList) varsC <- c(vars, "coef") vecMpolyList <- unclass(mpolyList) vecMpolyList <- lapply(vecMpolyList, unclass) vecMpolyList <- lapply(vecMpolyList, lapply, function(v){ if(names(v)[1] == "coef") return(v) o <- v["coef"] names(o) <- names(v)[1] o }) vecMpolyList <- lapply(vecMpolyList, unlist) vecMpolyList <- lapply(vecMpolyList, function(x){ varsNeeded <- setdiff(varsC, names(x)) if(length(varsNeeded) > 0){ tmp <- rep(0, length(varsNeeded)) names(tmp) <- varsNeeded x <- c(x, tmp) x <- x[varsC] } x }) vecMpolyList <- lapply(vecMpolyList, function(x){ df <- as.data.frame(t(x)) row.names(df) <- runif(1) # another way? df }) vecMpolyList <- unsplit(vecMpolyList, 1:length(vecMpolyList), drop = TRUE) row.names(vecMpolyList) <- 1:nrow(vecMpolyList) as.matrix(vecMpolyList) } latte/R/zsolve.R0000644000176200001440000001035013445173011013227 0ustar liggesusers#' Solve a linear system over the integers #' #' zsolve runs 4ti2's zsolve program to compute the configuration matrix A #' corresponding to graphical statistical models given by a simplicial complex #' and levels on the nodes. #' #' @param mat The A matrix (see the 4ti2 documentation or examples) #' @param rel A vector of "<" or ">" relations #' @param rhs The right hand side b #' @param sign The signs of the individual #' @param lat A lattice basis (instead of a matrix) #' @param lb Lower bounds on columns #' @param ub Upper bounds on columns #' @param dir Directory to place the files in, without an ending / #' @param quiet If FALSE, messages the 4ti2 output #' @param shell Messages the shell code used to do the computation #' @param ... Additional arguments to pass to the function #' @return The configuration matrix of the model provided #' @export #' @examples #' #' if (has_4ti2()) { #' #' mat <- rbind( #' c( 1, -1), #' c(-3, 1), #' c( 1, 1) #' ) #' rel <- c("<", "<", ">") #' rhs <- c(2, 1, 1) #' sign <- c(0, 1) #' #' zsolve(mat, rel, rhs, sign) #' zsolve(mat, rel, rhs, sign, quiet = FALSE) #' zsolve(mat, rel, rhs, sign, shell = TRUE) #' #' zsolve(mat, rel, rhs, sign, p = "gmp", quiet = FALSE) #' #' } #' #' zsolve <- function(mat, rel, rhs, sign, lat, lb, ub, dir = tempdir(), quiet = TRUE, shell = FALSE, ... ){ if (!has_4ti2()) missing_4ti2_stop() ## compute other args opts <- as.list(match.call(expand.dots = FALSE))[["..."]] if(is.null(opts)){ opts <- "" } else { opts <- paste0("-", names(opts), "", unlist(opts)) opts <- paste(opts, collapse = " ") } ## create and move to dir #################################### ## make dir to put 4ti2 files in (within the tempdir) timestamped dir.create(scratch_dir <- file.path(dir, time_stamp())) ## switch to temporary directory user_working_directory <- getwd() setwd(scratch_dir); on.exit(setwd(user_working_directory), add = TRUE) ## arg check #################################### if(missing(mat) && missing(lat)) stop("Either mat or lat must be specified.", call. = FALSE) if(!missing(mat) && !all(is.wholenumber(mat))) stop("The entries of mat must all be integers.") if(!missing(lat) && !all(is.wholenumber(lat))) stop("The entries of lat must all be integers.") if(!missing(rhs) && !all(is.wholenumber(rhs))) stop("The entries of rhs must all be integers.") if(!all(rel %in% c("<", ">"))) stop("rel must be a vector of \"<\"'s or \">\"'s.") ## write files #################################### if(!missing(mat)) write.latte(mat, "system.mat") write.latte(t(rel), "system.rel") write.latte(t(rhs), "system.rhs") if(!missing(sign)) write.latte(t(sign), "system.sign") if(missing(mat) && !missing(lat)) write.latte(mat, "system.lat") if(!missing(lb)) write.latte(mat, "system.lb") if(!missing(ub)) write.latte(mat, "system.ub") ## move to dir and run 4it2 zsolve #################################### ## run 4ti2 if (is_mac() || is_unix()) { system2( file.path(get_4ti2_path(), "zsolve"), paste(opts, file.path(scratch_dir, "system")), stdout = "zsolve_out", stderr = "zsolve_err" ) # generate shell code shell_code <- glue( "{file.path(get_4ti2_path(), 'zsolve')} {paste(opts, file.path(scratch_dir, 'system'))} > zsolve_out 2> zsolve_err" ) if(shell) message(shell_code) } else if (is_win()) { matFile <- file.path(scratch_dir, "system") matFile <- chartr("\\", "/", matFile) matFile <- str_c("/cygdrive/c", str_sub(matFile, 3)) system2( "cmd.exe", glue("/c env.exe {file.path(get_4ti2_path(), 'zsolve')} {opts} {matFile}"), stdout = "zsolve_out", stderr = "zsolve_err" ) # generate shell code shell_code <- glue( "cmd.exe /c env.exe {file.path(get_4ti2_path(), 'zsolve')} {opts} {matFile} > zsolve_out 2> zsolve_err" ) if(shell) message(shell_code) } ## print output, if desired if(!quiet) message(paste(readLines("zsolve_out"), "\n")) std_err <- readLines("zsolve_err") if(any(std_err != "")) warning(str_c(std_err, collapse = "\n"), call. = FALSE) ## read and return list( zinhom = read.latte("system.zinhom"), zhom = read.latte("system.zhom") ) } latte/R/ppi.R0000644000176200001440000000462613445173121012510 0ustar liggesusers#' Compute the primitive partition identities #' #' ppi runs 4ti2's ppi program to compute the primitive partition identities, #' that is, the Graver basis of 1:N. #' #' @param N A postive integer > 2 #' @param dir Directory to place the files in, without an ending / #' @param quiet If FALSE, messages the 4ti2 output #' @param shell Messages the shell code used to do the computation #' @param ... Additional arguments to pass to the function #' @return A matrix containing the basis as its columns (for easy addition to #' tables) #' @seealso [graver()] #' @export #' @examples #' #' if (has_4ti2()) { #' #' ppi(3) #' t(ppi(3)) %*% 1:3 #' plot_matrix(ppi(3)) #' #' graver(t(1:3)) #' plot_matrix(graver(t(1:3))) #' #' ppi(5, quiet = FALSE, shell = TRUE) #' #' } #' #' ppi <- function(N, dir = tempdir(), quiet = TRUE, shell = FALSE, ...){ if (!has_4ti2()) missing_4ti2_stop() ## arg checking stopifnot(is.wholenumber(N) && N > 2) ## compute other args opts <- as.list(match.call(expand.dots = FALSE))[["..."]] if(is.null(opts)){ opts <- "" } else { opts <- str_c("-", names(opts), "", unlist(opts)) opts <- str_c(opts, collapse = " ") } ## move to dir and run 4it2 ppi #################################### ## make dir to put 4ti2 files in (within the tempdir) timestamped dir.create(scratch_dir <- file.path(dir, time_stamp())) ## switch to temporary directory user_working_directory <- getwd() setwd(scratch_dir); on.exit(setwd(user_working_directory), add = TRUE) ## run 4ti2 if (is_mac() || is_unix()) { system2( file.path(get_4ti2_path(), "ppi"), paste(opts, N), stdout = "ppi_out", stderr = "ppi_err" ) # generate shell code shell_code <- glue( "{file.path(get_4ti2_path(), 'ppi')} {paste(opts, file.path(scratch_dir, 'system'))} > ppi_out 2> ppi_err" ) if(shell) message(shell_code) } else if (is_win()) { system2( "cmd.exe", glue("/c env.exe {file.path(get_4ti2_path(), 'ppi')} {opts} {N}"), stdout = "ppi_out", stderr = "ppi_err" ) # generate shell code shell_code <- glue( "cmd.exe /c env.exe {file.path(get_4ti2_path(), 'ppi')} {opts} {N} > ppi_out 2> ppi_err" ) if(shell) message(shell_code) } ## print output, if desired if(!quiet) cat(readLines("ppi_out"), sep = "\n") ## read and return t(read.latte(str_c("ppi", N, ".gra"))) } latte/R/lattice-bases.R0000644000176200001440000002430313445173031014432 0ustar liggesusers#' Compute a basis with 4ti2 #' #' 4ti2 provides several executables that can be used to generate bases for a #' configuration matrix A. See the references for details. #' #' @param A The configuration matrix #' @param format How the basis (moves) should be returned. if "mat", the moves #' are returned as the columns of a matrix. #' @param dim The dimension to be passed to [vec2tab()] if format = "tab" is #' used; a vector of the number of levels of each variable in order #' @param all If TRUE, all moves (+ and -) are given. if FALSE, only the + #' moves are given as returned by the executable. #' @param dir Directory to place the files in, without an ending / #' @param quiet If FALSE, messages the 4ti2 output #' @param shell Messages the shell code used to do the computation #' @param dbName The name of the model in the markov bases database, #' http://markov-bases.de, see examples #' @param ... Additional arguments to pass to the function, e.g. \code{p = #' "arb"} specifies the flag \code{-parb}; not setting this issues a common #' warning #' @return a matrix containing the Markov basis as its columns (for easy #' addition to tables) #' @name lattice-bases #' @references Drton, M., B. Sturmfels, and S. Sullivant (2009). \emph{Lectures #' on Algebraic Statistics}, Basel: Birkhauser Verlag AG. #' @examples #' #' #' if (has_4ti2()) { #' #' #' # basic input and output for the 3x3 independence example #' (A <- rbind( #' kprod(diag(3), ones(1,3)), #' kprod(ones(1,3), diag(3)) #' )) #' markov(A, p = "arb") #' #' #' #' # you can get the output formatted in different ways: #' markov(A, p = "arb", all = TRUE) #' markov(A, p = "arb", "vec") #' markov(A, p = "arb", "tab", c(3, 3)) #' tableau(markov(A, p = "arb"), dim = c(3, 3)) # tableau notation #' #' #' #' # you can add options by listing them off #' # to see the options available to you by function, #' # go to http://www.4ti2.de #' markov(A, p = "arb") #' #' #' #' # the basis functions are automatically cached for future use. #' # (note that it doesn't persist across sessions.) #' A <- rbind( #' kprod( diag(4), ones(1,4), ones(1,4)), #' kprod(ones(1,4), diag(4), ones(1,4)), #' kprod(ones(1,4), ones(1,4), diag(4)) #' ) #' system.time(markov(A, p = "arb")) #' system.time(markov(A, p = "arb")) #' #' # the un-cashed versions begin with an "f" #' # (think: "forgetful" markov) #' system.time(fmarkov(A, p = "arb")) #' system.time(fmarkov(A, p = "arb")) #' #' #' #' # you can see the command line code by typing shell = TRUE #' # and the standard output wiht quiet = FALSE #' # we illustrate these with fmarkov because otherwise it's cached #' (A <- rbind( #' kprod(diag(2), ones(1,4)), #' kprod(ones(1,4), diag(2)) #' )) #' fmarkov(A, p = "arb", shell = TRUE) #' fmarkov(A, p = "arb", quiet = FALSE) #' #' #' #' # compare the bases for the 3x3x3 no-three-way interaction model #' A <- rbind( #' kprod( diag(3), diag(3), ones(1,3)), #' kprod( diag(3), ones(1,3), diag(3)), #' kprod(ones(1,3), diag(3), diag(3)) #' ) #' str( zbasis(A, p = "arb")) # 8 elements = ncol(A) - qr(A)$rank #' str( markov(A, p = "arb")) # 81 elements #' str(groebner(A, p = "arb")) # 110 elements #' str( graver(A)) # 795 elements #' #' #' # the other bases are also cached #' A <- rbind( #' kprod( diag(3), ones(1,3), ones(1,2)), #' kprod(ones(1,3), diag(3), ones(1,2)), #' kprod(ones(1,3), ones(1,3), diag(2)) #' ) #' system.time( graver(A)) #' system.time( graver(A)) #' system.time(fgraver(A)) #' system.time(fgraver(A)) #' #' #' #' # LAS ex 1.2.1, p.12 : 2x3 independence #' (A <- rbind( #' kprod(diag(2), ones(1,3)), #' kprod(ones(1,2), diag(3)) #' )) #' #' markov(A, p = "arb", "tab", c(3, 3)) #' # Prop 1.2.2 says that there should be #' 2*choose(2, 2)*choose(3,2) # = 6 #' # moves (up to +-1) #' markov(A, p = "arb", "tab", c(3, 3), TRUE) #' #' #' #' # LAS example 1.2.12, p.17 (no 3-way interaction) #' (A <- rbind( #' kprod( diag(2), diag(2), ones(1,2)), #' kprod( diag(2), ones(1,2), diag(2)), #' kprod(ones(1,2), diag(2), diag(2)) #' )) #' plot_matrix(A) #' markov(A, p = "arb") #' groebner(A, p = "arb") #' graver(A) #' tableau(markov(A, p = "arb"), dim = c(2,2,2)) #' #' #' #' #' #' # using the markov bases database, must be connected to internet #' # commented out for predictable and fast cran checks time #' # A <- markov(dbName = "ind3-3") #' # B <- markov(rbind( #' # kprod(diag(3), ones(1,3)), #' # kprod(ones(1,3), diag(3)) #' # ), p = "arb") #' # all(A == B) #' #' #' #' #' #' # possible issues #' # markov(diag(1, 10)) #' # zbasis(diag(1, 10), "vec") #' # groebner(diag(1, 10), "vec", all = TRUE) #' # graver(diag(1, 10), "vec", all = TRUE) #' # graver(diag(1, 4), "tab", all = TRUE, dim = c(2,2)) #' #' #' #' } #' #' #' @param exec don't use this parameter #' @param memoise don't use this parameter basis <- function(exec, memoise = TRUE){ ## stuff in basis extension <- switch(exec, markov = ".mar", groebner = ".gro", hilbert = ".hil", graver = ".gra", zbasis = ".lat", zsolve = ".zfree" ) commonName <- switch(exec, markov = "markov", groebner = "grobner", hilbert = "hilbert", graver = "graver", zbasis = "lattice", zsolve = "solve" ) ## memoise or not mem_or_not <- if(memoise) memoise::memoise else (function(x) x) ## create the function to return mem_or_not(function(A, format = c("mat", "vec", "tab"), dim = NULL, all = FALSE, dir = tempdir(), quiet = TRUE, shell = FALSE, dbName = NULL, ... ){ if (!has_4ti2()) missing_4ti2_stop() ## check args format <- match.arg(format) if (format == "tab" && missing(dim)) { stop('If format = "tab" is specified, dim must be also.', call. = FALSE) } ## compute other args opts <- as.list(match.call(expand.dots = FALSE))[["..."]] if (is.null(opts)) { opts <- "" } else { opts <- str_c("-", names(opts), "", unlist(opts)) opts <- str_c(opts, collapse = " ") } ## make dir to put 4ti2 files in (within the tempdir) timestamped dir.create(scratch_dir <- file.path(dir, time_stamp())) ## make 4ti2 file if(!missing(A)) write.latte(A, file.path(scratch_dir, "PROJECT.mat")) ## switch to temporary directory user_working_directory <- getwd() setwd(scratch_dir); on.exit(setwd(user_working_directory), add = TRUE) ## create/retrieve markov basis if (is.null(dbName)) { ## run 4ti2 if needed if (is_mac() || is_unix()) { system2( file.path(get_4ti2_path(), exec), paste(opts, file.path(scratch_dir, "PROJECT")), stdout = glue("{exec}_out"), stderr = glue("{exec}_err") ) # generate shell code shell_code <- glue( "{file.path(get_4ti2_path(), exec)} {paste(opts, file.path(scratch_dir, 'PROJECT'))} > {exec}_out 2> {exec}_err" ) if(shell) message(shell_code) } else if (is_win()) { matFile <- file.path(scratch_dir, "PROJECT") matFile <- chartr("\\", "/", matFile) matFile <- str_c("/cygdrive/c", str_sub(matFile, 3)) system2( "cmd.exe", glue("/c env.exe {file.path(get_4ti2_path(), exec)} {opts} {matFile}"), stdout = glue("{exec}_out"), stderr = glue("{exec}_err") ) # generate shell code shell_code <- glue( "cmd.exe /c env.exe {file.path(get_4ti2_path(), exec)} {opts} {matFile} > {exec}_out 2> {exec}_err" ) if(shell) message(shell_code) } if(!quiet) cat(readLines(glue("{exec}_out")), sep = "\n") std_err <- readLines(glue("{exec}_err")) if(any(std_err != "")) warning(str_c(std_err, collapse = "\n"), call. = FALSE) } else { # if the model name is specified download.file( paste0("http://markov-bases.de/data/", dbName, "/", dbName, extension), destfile = "PROJECT.mar" # already in tempdir ) } ## fix case of no graver basis if(exec == "graver"){ if(paste0("PROJECT", extension) %notin% list.files(scratch_dir)){ warning(sprintf("%s basis empty, returning 0's.", capitalize(commonName)), call. = FALSE) return(fix_graver(A, format, dim)) } } ## figure out what files to keep them, and make 4ti2 object basis <- t(read.latte(paste0("PROJECT", extension))) ## fix case of no basis basisDim <- dim(basis) noBasisFlag <- FALSE if(any(basisDim == 0)){ noBasisFlag <- TRUE warning(sprintf("%s basis empty, returning 0's.", capitalize(commonName)), call. = FALSE) basisDim[basisDim == 0] <- 1L basis <- rep(0L, prod(basisDim)) dim(basis) <- basisDim } ## format if(all && !noBasisFlag) basis <- cbind(basis, -basis) # out if(format == "mat"){ return(basis) } else { lbasis <- as.list(rep(NA, ncol(basis))) for(k in 1:ncol(basis)) lbasis[[k]] <- basis[,k] if(format == "vec") return(lbasis) if(format == "tab") return(lapply(lbasis, vec2tab, dim = dim)) } }) } # #' @export # #' @rdname lattice-bases # zsolve <- basis("zsolve", memoise = TRUE) #' @export #' @rdname lattice-bases zbasis <- basis("zbasis", memoise = TRUE) #' @export #' @rdname lattice-bases markov <- basis("markov", memoise = TRUE) #' @export #' @rdname lattice-bases groebner <- basis("groebner", memoise = TRUE) #' @export #' @rdname lattice-bases hilbert <- basis("hilbert", memoise = TRUE) #' @export #' @rdname lattice-bases graver <- basis("graver", memoise = TRUE) # #' @export # #' @rdname lattice-bases # fzsolve <- basis("zsolve", memoise = FALSE) #' @export #' @rdname lattice-bases fzbasis <- basis("zbasis", memoise = FALSE) #' @export #' @rdname lattice-bases fmarkov <- basis("markov", memoise = FALSE) #' @export #' @rdname lattice-bases fgroebner <- basis("groebner", memoise = FALSE) #' @export #' @rdname lattice-bases fhilbert <- basis("hilbert", memoise = FALSE) #' @export #' @rdname lattice-bases fgraver <- basis("graver", memoise = FALSE) fix_graver <- function(A, format, dim){ if(format == "mat"){ return(matrix(0L, nrow = ncol(A))) } else { lbasis <- list(rep(0L, ncol(A))) if(format == "vec") return(lbasis) if(format == "tab") return(lapply(lbasis, vec2tab, dim = dim)) } } latte/R/call-latte.R0000644000176200001440000000310113453377457013746 0ustar liggesusers#' Unified interface to calling LattE #' #' Unified interface to calling LattE #' #' @param which_exe The name of LattE executable, e.g. \code{"count"} #' @param input_file The filename of file to be given to the executable, without #' a path #' @param project_dir The path associated with \code{input_file}. #' @param opts A named list of optional command line arguments to the #' executable. #' @param stdout,stderr Filenames to redirect standard output and standard error #' to. #' @param shell \code{logical(1)}; should the shell command be messaged to the #' user? #' @return \code{invisible()} call_latte <- function( which_exe, input_file, project_dir, opts = list(), stdout = "stdout", stderr = "stderr", shell = FALSE ) { # translate args to string if (length(opts) == 0L) { opts <- "" } else { opts_names <- names(opts) opts_names <- str_replace_all(opts_names, "_", "-") opts <- str_c("--", opts_names, "=", unlist(opts)) opts <- str_replace_all(opts, "=TRUE", "") opts <- str_c(opts, collapse = " ") } # make call if (is_mac() || is_unix()) { system2( file.path(get_latte_path(), which_exe), paste(opts, file.path(project_dir, input_file)), stdout = stdout, stderr = stderr ) } else if (is_win()) { matFile <- file.path(project_dir, input_file) matFile <- chartr("\\", "/", matFile) matFile <- str_c("/cygdrive/c", str_sub(matFile, 3)) system2( "cmd.exe", paste("/c env.exe", file.path(get_latte_path(), which_exe), opts, matFile), stdout = stdout, stderr = stderr ) } invisible() }latte/R/qsolve.R0000644000176200001440000000731013445173102013221 0ustar liggesusers#' Solve a linear system over the rationals #' #' qsolve runs 4ti2's qsolve program to compute the #' configuration matrix A corresponding to graphical statistical #' models given by a simplicial complex and levels on the nodes. #' #' @param mat The A matrix (see the 4ti2 documentation or examples) #' @param rel A vector of "<" or ">" relations #' @param sign The signs of the individual #' @param dir Directory to place the files in, without an ending / #' @param quiet If FALSE, messages the 4ti2 output #' @param shell Messages the shell code used to do the computation #' @param ... Additional arguments to pass to the function #' @return The configuration matrix of the model provided #' @export #' @examples #' #' if (has_4ti2()) { #' #' # x + y > 0 #' # x + y < 0 #' #' mat <- rbind( #' c( 1, 1), #' c( 1, 1) #' ) #' rel <- c(">", "<") #' sign <- c(0, 0) #' #' qsolve(mat, rel, sign, p = "arb") #' qsolve(mat, rel, sign, p = "arb", quiet = FALSE) #' qsolve(mat, rel, sign, p = "arb", shell = TRUE) #' #' } #' #' qsolve <- function(mat, rel, sign, dir = tempdir(), quiet = TRUE, shell = FALSE, ... ){ if (!has_4ti2()) missing_4ti2_stop() ## compute other args opts <- as.list(match.call(expand.dots = FALSE))[["..."]] if("rhs" %in% names(opts)) stop("qsolve only solve homogeneous systems (b = 0).") if(is.null(opts)){ opts <- "" } else { opts <- paste0("-", names(opts), "", unlist(opts)) opts <- paste(opts, collapse = " ") } ## create and move to dir #################################### ## make dir to put 4ti2 files in (within the tempdir) timestamped dir.create(scratch_dir <- file.path(dir, time_stamp())) ## switch to temporary directory user_working_directory <- getwd() setwd(scratch_dir); on.exit(setwd(user_working_directory), add = TRUE) ## arg check #################################### if(!missing(mat) && !all(is.wholenumber(mat))) stop("The entries of mat must all be integers.") if(!missing(sign) && !all(is.wholenumber(sign))) stop("The entries of sign must all be integers.") if(!all(rel %in% c("<", ">"))) stop("rel must be a vector of \"<\"'s or \">\"'s.") ## write files #################################### if(!missing(mat)) write.latte(mat, "system.mat") write.latte(t(rel), "system.rel") if(!missing(sign)) write.latte(t(sign), "system.sign") ## move to dir and run 4it2 qsolve #################################### ## run 4ti2 if (is_mac() || is_unix()) { system2( file.path(get_4ti2_path(), "qsolve"), paste(opts, file.path(scratch_dir, "system")), stdout = "qsolve_out", stderr = "qsolve_err" ) # generate shell code shell_code <- glue( "{file.path(get_4ti2_path(), 'qsolve')} {paste(opts, file.path(scratch_dir, 'system'))} > qsolve_out 2> qsolve_err" ) if(shell) message(shell_code) } else if (is_win()) { matFile <- file.path(scratch_dir, "system") matFile <- chartr("\\", "/", matFile) matFile <- str_c("/cygdrive/c", str_sub(matFile, 3)) system2( "cmd.exe", glue("/c env.exe {file.path(get_4ti2_path(), 'qsolve')} {opts} {matFile}"), stdout = "qsolve_out", stderr = "qsolve_err" ) # generate shell code shell_code <- glue( "cmd.exe /c env.exe {file.path(get_4ti2_path(), 'qsolve')} {opts} {matFile} > qsolve_out 2> qsolve_err" ) if(shell) message(shell_code) } ## print output, if desired if(!quiet) message(paste(readLines("qsolve_out"), "\n")) std_err <- readLines("qsolve_err") if(any(std_err != "")) warning(str_c(std_err, collapse = "\n"), call. = FALSE) ## read and return list( qhom = read.latte("system.qhom"), qfree = read.latte("system.qfree") ) } latte/R/helpers.R0000644000176200001440000000242413445215073013357 0ustar liggesusers rhash <- function(n) { paste( sample(c(letters, LETTERS, 0:9), n, replace = TRUE), collapse = "" ) } # rhash(10) time_stamp <- function(){ time_stamp <- as.character(Sys.time()) time_stamp <- chartr("-", "_", time_stamp) time_stamp <- chartr(" ", "_", time_stamp) time_stamp <- chartr(":", "_", time_stamp) time_stamp <- paste0(time_stamp, "_", rhash(10)) time_stamp } # time_stamp() is.wholenumber <- function(x, tol = .Machine$double.eps^0.5) abs(x - round(x)) < tol file.path2 <- function(...){ dots <- list(...) if(.Platform$OS.type == "unix"){ sep <- "/" } else { sep <- "\\" } paste0(dots, collapse = sep) } is.formula <- function(x) inherits(x, "formula") is_mac <- function() grepl("darwin", R.version$platform) is_win <- function() .Platform$OS.type == "windows" is_linux <- function() (.Platform$OS.type == "unix") && !is_mac() is_unix <- function() .Platform$OS.type == "unix" is_solaris <- function() grepl("solaris", R.version$os) capitalize <- function(s){ if(length(s) > 1) return(vapply(s, capitalize, character(1))) str_c(toupper(str_sub(s, 1, 1)), str_sub(s, 2)) } `%notin%` <- function(elem, set){ if(length(elem) > 1) return(vapply(elem, `%notin%`, logical(1), set = set)) !(elem %in% set) } latte/R/tableau.R0000644000176200001440000000441614263604150013332 0ustar liggesusers#' Tableau Notation for Markov #' #' Print the tableau notation for a Markov move. See the reference #' provided, p. 13. #' #' @param move a markov move matrix, where the columns are moves in #' vector form (e.g. the output of markov) #' @param dim the dimensions of the table form of the move, #' oftentimes a vector of the number of levels of each variable in #' order #' @return an object of class tableau #' @export tableau #' @references Drton, M., B. Sturmfels, and S. Sullivant (2009). #' \emph{Lectures on Algebraic Statistics}, Basel: Birkhauser #' Verlag AG. #' @examples #' #' vec <- matrix(c(1, -1, -1, 1), nrow = 4) #' varlvls <- c(2, 2) #' tableau(vec, varlvls) #' #' tableau <- function(move, dim){ if(is.vector(move) && (is.integer(move) || is.numeric(move))) move <- t(t(move)) if(ncol(move) == 1){ p <- length(dim) move <- t(t(tab2vec(vec2tab(move, dim)))) row.names(move) <- str_replace_all(row.names(move), ",", "") t1 <- row.names(move)[move > 0] t1 <- matrix( unlist(lapply(strsplit(t1, ''), as.numeric)), ncol = p, byrow = TRUE ) t2 <- row.names(move)[move < 0] t2 <- matrix( unlist(lapply(strsplit(t2, ''), as.numeric)), ncol = p, byrow = TRUE ) out <- list(t1, t2) } else { out <- list() for(k in 1:ncol(move)){ out[[k]] <- tableau(move[,k,drop = FALSE], dim = dim) } } class(out) <- 'tableau' out } #' Pretty printing of tableau output. #' #' Pretty printing of tableau output. #' #' @param x an object of class tableau #' @param ... ... #' @usage \method{print}{tableau}(x, ...) #' @return Invisible string of the printed object. #' @export #' @examples #' #' # see ?tableau #' #' print.tableau <- function(x, ...){ if((length(x) == 2) && all(sapply(x, is.matrix))){ plus <- x[[1]] minus <- x[[2]] p <- ncol(x[[1]]) changes <- nrow(x[[1]]) for(k in 1:changes){ if(k == floor(changes/2)){ sep <- ' - ' } else { sep <- ' ' } line2print <- paste( paste(plus[k,], collapse = ' '), sep, paste(minus[k,], collapse = ' '),'\n' ) cat(line2print) } } else { for(k in 1:length(x)){ print.tableau(x[[k]]) if(k < length(x)) cat('\n') } } } latte/R/plot-matrix.R0000644000176200001440000000261013442001070014155 0ustar liggesusers#' Plot a matrix #' #' plot_matrix is a R variant of Matlab's \code{spy} function. #' #' @param A A matrix #' @return a ggplot object #' @author David Kahle \email{david@@kahle.io} #' @name plot-matrix #' @examples #' #' # the no-three-way interaction configuration #' (A <- kprod(ones(1,3), diag(3), ones(3))) #' plot_matrix(A) #' #' #' if (has_4ti2()) { #' #' plot_matrix(markov(A)) #' #' (A <- genmodel(c(2L, 2L), list(1L, 2L))) #' plot_matrix(A) #' plot_matrix(markov(A)) #' #' (A <- genmodel(c(5L, 5L), list(1L, 2L))) #' plot_matrix(A) #' plot_matrix(markov(A)) #' #' } #' #' @rdname plot-matrix #' @export plot_matrix <- function(A){ x <- NULL; rm(x) y <- NULL; rm(y) low <- if(any(A < 0)){ low <- "blue"; high <- "red" fillScale <- scale_fill_gradient2( low = "blue", mid = "grey80", high = "red", midpoint = 0, guide = FALSE, space = "Lab" ) } else { fillScale <- scale_fill_gradient( low = "white", high = "black", guide = FALSE ) } df <- expand.grid(x = 1:ncol(A), y = 1:nrow(A)) B <- t(A) df$A <- as.integer(B[,ncol(B):1]) ggplot(df, aes(x, y, fill = A)) + geom_tile() + fillScale + theme_bw() + coord_equal() + scale_x_continuous(expand = c(0,0)) + scale_y_continuous(expand = c(0,0)) + theme( line = element_blank(), text = element_blank(), plot.margin = grid::unit(c(0, 0, 0, 0), "lines") ) } latte/R/latte-optim.R0000644000176200001440000001533615021465122014154 0ustar liggesusers#' Solve an integer progam with LattE #' #' [latte_max()] and [latte_min()] use LattE's `latte-maximize` and #' `latte-minimize` functions to find the maximum or minimum of a linear #' objective function over the integers points in a polytope (i.e. satisfying #' linearity constraints). This makes use of the digging algorithm; see the #' LattE manual at \url{https://www.math.ucdavis.edu/~latte/} for details. #' #' @param objective A linear polynomial to pass to [mpoly::mp()], see examples #' @param constraints A collection of linear polynomial (in)equalities that #' define the feasibility region, the integers in the polytope #' @param method Method `"LP"` or `"cones"` #' @param dir Directory to place the files in, without an ending `/` #' @param opts Options; see the LattE manual at #' \url{https://www.math.ucdavis.edu/~latte/} #' @param quiet Show latte output #' @param shell Messages the shell code used to do the computation #' @param type `"max"` or `"min"` #' @return A named list with components `par`, a named-vector of optimizing #' arguments, and `value`, the value of the objective function at the optimial #' point. #' @name latte-optim #' @examples #' #' #' if (has_latte()) { #' #' latte_max( #' "-2 x + 3 y", #' c("x + y <= 10", "x >= 0", "y >= 0") #' ) #' #' latte_max( #' "-2 x + 3 y", #' c("x + y <= 10", "x >= 0", "y >= 0"), #' quiet = FALSE #' ) #' #' #' df <- expand.grid("x" = 0:10, "y" = 0:10) #' df <- subset(df, x + y <= 10L) #' df$objective <- with(df, -2*x + 3*y) #' library("ggplot2") #' ggplot(df, aes(x, y, size = objective)) + #' geom_point() #' #' latte_min( #' "-2 x + 3 y", #' c("x + y <= 10", "x >= 0", "y >= 0"), #' method = "cones" #' ) #' #' #' #' latte_min("-2 x - 3 y - 4 z", c( #' "3 x + 2 y + z <= 10", #' "2 x + 5 y + 3 z <= 15", #' "x >= 0", "y >= 0", "z >= 0" #' ), "cones", quiet = FALSE) #' #' #' #' #' #' } #' latte_optim <- function( objective, constraints, type = c("max", "min"), method = c("lp","cones"), dir = tempdir(), opts = "", quiet = TRUE, shell = FALSE ){ if (!has_latte()) missing_latte_stop() type <- match.arg(type) method <- match.arg(method) ## set executable to use exec <- if(type == "max") "latte-maximize" else "latte-minimize" ## parse objective if(is.character(objective)) objective <- mp(objective) stopifnot(is.linear(objective)) ## parse constraints into the poly <= 0 format nConstraints <- length(constraints) if(is.character(constraints) && nConstraints > 1){ parsedCons <- as.list(rep(NA, nConstraints)) geqNdcs <- which(str_detect(constraints, " >= ")) leqNdcs <- which(str_detect(constraints, " <= ")) eeqNdcs <- which(str_detect(constraints, " == ")) eqNdcs <- which(str_detect(constraints, " = ")) if(length(geqNdcs) > 0){ tmp <- strsplit(constraints[geqNdcs], " >= ") parsedCons[geqNdcs] <- lapply(tmp, function(v) mp(v[2]) - mp(v[1])) } if(length(leqNdcs) > 0){ tmp <- strsplit(constraints[leqNdcs], " <= ") parsedCons[leqNdcs] <- lapply(tmp, function(v) mp(v[1]) - mp(v[2])) } if(length(eeqNdcs) > 0){ tmp <- strsplit(constraints[eeqNdcs], " == ") parsedCons[eeqNdcs] <- lapply(tmp, function(v) mp(v[1]) - mp(v[2])) } if(length(eqNdcs) > 0){ tmp <- strsplit(constraints[eqNdcs], " = ") parsedCons[eqNdcs] <- lapply(tmp, function(v) mp(v[1]) - mp(v[2])) } linearityNdcs <- sort(c(eeqNdcs, eqNdcs)) constraints <- parsedCons class(constraints) <- "mpolyList" if (!all(is.linear(constraints))) stop("all polynomials must be linear.", call. = FALSE) } ## mpoly_list_to_mat is in file count.r matFull <- mpoly_list_to_mat( structure( c(list(objective), constraints), class = "mpolyList" ) ) ## make dir to put latte files in (within the tempdir) timestamped dir.create(scratch_dir <- file.path(dir, time_stamp())) ## switch to temporary directory user_working_directory <- getwd() setwd(scratch_dir); on.exit(setwd(user_working_directory), add = TRUE) ## convert constraints to latte hrep code and write file mat <- cbind( -matFull[-1,"coef",drop=FALSE], -matFull[-1,-ncol(matFull)] ) if(length(linearityNdcs) > 0) attr(mat, "linearity") <- linearityNdcs ## note: the nonnegative stuff is built into this write.latte(mat, "optim_code") ## convert objective to latte hrep code and write file mat <- cbind( matFull[1,"coef",drop=FALSE], matFull[1,-ncol(matFull),drop=FALSE] )[,-1, drop = FALSE] write.latte(mat, "optim_code.cost") ## run latte function if (is_mac() || is_unix()) { system2( file.path(get_latte_path(), exec), paste(opts, file.path(scratch_dir, "optim_code")), stdout = glue("optim_out"), stderr = glue("optim_err") ) # generate shell code shell_code <- glue( "{file.path(get_latte_path(), exec)} {paste(opts, file.path(scratch_dir, 'optim_code'))} > {exec}_out 2> {exec}_err" ) if(shell) message(shell_code) } else if(is_win()){ # windows matFile <- file.path(scratch_dir, "optim_code 2> out.txt") matFile <- chartr("\\", "/", matFile) matFile <- str_c("/cygdrive/c", str_sub(matFile, 3)) system( paste( paste0("cmd.exe /c env.exe"), file.path(get_latte_path(), exec), opts, matFile ), intern = FALSE, ignore.stderr = FALSE ) } ## print count output when quiet = FALSE std_out <- readLines("optim_out") if(!quiet) cat(std_out, sep = "\n") # note: strangely, latte posts non-error info to stderr std_err <- readLines("optim_err") if(!quiet && any(std_err != "")) message(str_c(std_err, collapse = "\n")) ## parse output if (method == "cones") { optimal_solution_string <- std_err[str_which(std_err, "An optimal solution")] } else { optimal_solution_string <- std_err[str_which(std_err, "A vertex which we found")] } optimal_solution_string <- str_extract(optimal_solution_string, "\\[-?\\d+( -?\\d+)+\\].?$") par <- as.integer(str_extract_all(optimal_solution_string, "-?\\d+")[[1]]) names(par) <- colnames(matFull)[1:(ncol(matFull)-1)] val <- str_extract(std_err, "(?<=The optimal value is: )-?\\d+") val <- as.integer(val[!is.na(val)]) ## out list(par = par, value = val) } #' @rdname latte-optim #' @export latte_max <- function(objective, constraints, method = c("lp","cones"), dir = tempdir(), opts = "", quiet = TRUE ){ latte_optim(objective, constraints, "max", method, dir, opts, quiet) } #' @rdname latte-optim #' @export latte_min <- function(objective, constraints, method = c("lp","cones"), dir = tempdir(), opts = "", quiet = TRUE ){ latte_optim(objective, constraints, "min", method, dir, opts, quiet) } latte/R/latte-files.R0000644000176200001440000001037413442214162014124 0ustar liggesusers#' Format/read/write a matrix in latte's style #' #' [format_latte()] formats a matrix in latte's style. #' [write_latte()] writes a latte-formatted file to file. #' [read_latte()] reads a latte-formatted file from disk. #' #' @param mat A matrix #' @param file A filename #' @param format "mat" or "Ab" #' @return \itemize{ #' #' \item [format_latte()] -- A character string of the matrix in #' latte format. #' #' \item [write_latte()] -- An invisible character #' string of the formatted output. #' #' \item [read_latte()] -- An integer matrix. #' #' } #' @name latte-files #' @examples #' #' #' (mat <- matrix(sample(9), 3, 3)) #' #' format_latte(mat) #' cat(format_latte(mat)) #' #' (file <- file.path(tempdir(), "foo.hrep")) #' write_latte(mat, file) #' file.show(file) #' read_latte(file) #' read_latte(file, "Ab") #' #' attr(mat, "linearity") <- c(1, 3) #' attr(mat, "nonnegative") <- 2 #' mat #' format_latte(mat) #' cat(format_latte(mat)) #' write_latte(mat, file) #' file.show(file) #' read_latte(file) #' #' file.remove(file) #' #' #' #' @rdname latte-files #' @export format_latte <- function(mat, file){ ## construct file in latte format ## e.g. "3 3\n5 6 8\n7 3 4\n2 9 1" ## and cat("3 3\n5 6 8\n7 3 4\n2 9 1") r <- nrow(mat) c <- ncol(mat) a <- attributes(mat) mat <- apply(mat, 2, format, scientific = FALSE) attributes(mat) <- a out <- paste(r, c) out <- paste0(out, "\n") out <- paste0(out, paste( apply(unname(mat), 1, paste, collapse = " "), collapse = "\n" ) ) ## add linearity lines, if present if("linearity" %in% names(attributes(mat))){ linLines <- attr(mat, "linearity") linLineToAdd <- paste( "linearity", length(linLines), paste(linLines, collapse = " ") ) out <- paste(out, linLineToAdd, sep = "\n") } ## add nonnegative lines, if present if("nonnegative" %in% names(attributes(mat))){ nnegLines <- attr(mat, "nonnegative") nnegLineToAdd <- paste( "nonnegative", length(nnegLines), paste(nnegLines, collapse = " ") ) out <- paste(out, nnegLineToAdd, sep = "\n") } ## return out } #' @rdname latte-files #' @export write_latte <- function(mat, file){ ## arg check if(missing(file)) stop("file (a filename) must be provided.") ## format out <- format_latte(mat) ## save it to disk and return if(!missing(file)) writeLines(out, con = file) ## invisibly return code invisible(out) } #' @rdname latte-files #' @export write.latte <- write_latte #' @rdname latte-files #' @export read_latte <- function(file, format = c("mat", "Ab")){ ## check args format <- match.arg(format) ## read in file ## e.g. [1] "3 3" "7 2 1" "6 3 4" "9 8 5" contents <- readLines(file) ## eliminate dimensions ## e.g. [1] "7 2 1" "6 3 4" "9 8 5" dim <- as.integer(str_split(str_trim(contents[1]), " ")[[1]]) ## if only one line, return empty int matrix if(length(contents) == 1){ out <- integer(0) dim(out) <- dim return(out) } ## split and parse, result is list matRows <- lapply( str_split(str_trim(contents[2:(1+dim[1])]), " "), function(x) as.integer(x[nchar(x) > 0]) ) ## put into matrix mat <- t(simplify2array(matRows)) ## check for linearity or nonnegative lines if(length(contents) > 1 + dim[1]){ # isolate the added lines addedLines <- contents[-(1:(1 + dim[1]))] # look for linearity, assume only one such line linQ <- str_detect(addedLines, "linearity") if(any(linQ)){ linLine <- addedLines[linQ] linStuff <- str_replace(linLine, "linearity ", "") linNdcs <- as.integer(str_split(linStuff, " ")[[1]][-1]) attr(mat, "linearity") <- linNdcs } # look for nonnegative, assume only one such line nnegQ <- str_detect(addedLines, "nonnegative") if(any(nnegQ)){ nnegLine <- addedLines[nnegQ] nnegStuff <- str_replace(nnegLine, "nonnegative ", "") nnegNdcs <- as.integer(str_split(nnegStuff, " ")[[1]][-1]) attr(mat, "nonnegative") <- nnegNdcs } } ## format if(format == "mat"){ return(mat) } else if(format == "Ab"){ return(list(A = -mat[,-1,drop=FALSE], b = mat[,1])) } } #' @rdname latte-files #' @export read.latte <- read_latte latte/R/kprod.R0000644000176200001440000000156014774757000013043 0ustar liggesusers#' Iterated Kronecker product #' #' Compute the Kronecker product of several matrices. #' #' If kronecker is the function that computes A x B, kprod computes A x B x C #' and so on; it's a wrapper of Reduce and kronecker. #' #' @param ... A listing of matrices #' @param FUN A function to pass to [base::kronecker()] #' @return A matrix that is the kronecker product of the specified matrices #' (from left to right). #' @export #' @examples #' #' kprod(diag(2), t(ones(2))) #' kprod(t(ones(2)), diag(2)) #' #' #' kprod(diag(2), t(ones(2)), t(ones(2))) #' kprod(t(ones(2)), diag(2), t(ones(2))) #' kprod(t(ones(2)), t(ones(2)), diag(2)) #' #' #' # cf. aoki, hara, and takemura p.13 #' rbind( #' kprod(diag(2), t(ones(2))), #' kprod(t(ones(2)), diag(2)) #' ) #' #' kprod <- function(..., FUN = `*`) { Reduce( function(X, Y) kronecker(X, Y, FUN), list(...) ) } latte/R/set-paths.R0000644000176200001440000000745114774757513013652 0ustar liggesusers#' Set paths to LattE and 4ti2 executables #' #' These are helper functions that deal with pathing to external programs and #' asking if they are present. When latte is loaded it attempts to find LattE #' and 4ti2 executables by looking for environment variables specifying them, #' i.e. their paths as specified in your `.Renviron` file. #' #' For easiest use, you'll want to specify the paths of LattE and 4ti2 #' executables in your `~/.Renviron` file. They should look something like #' #' `LATTE=/Applications/latte/bin` #' #' `FOURTITWO=/Applications/latte/bin` #' #' You can set these permanently with [usethis::edit_r_environ()]. #' #' You can change these for the current session using, e.g., [set_latte_path()], #' which accepts a character string or, if missing, uses [file.choose()] to let #' you interactively; you just select an arbitrary executable. #' #' @param path A character string, the path to a 4ti2 function (e.g. `markov`) #' for setting 4ti2's path or a LattE function (e.g. `count`) for LattE's path #' @return A logical(1) or character(1) containing the path. #' @name pathing #' @author David Kahle \email{david@@kahle.io} #' @examples #' #' #' has_4ti2() #' if (has_4ti2()) get_4ti2_path() #' #' has_latte() #' if (has_4ti2()) get_latte_path() #' #' #' # you can set these paths permanently with the following. note that you'll #' # need to re-start the R session afterwards or simply pass the path into, #' # e.g., set_latte_path(). see below for more details on that. #' if (interactive()) edit_r_environ() #' #' #' # you can change these in your current session with set_latte_path() and #' if (had_latte <- has_latte()) old_latte_path <- get_latte_path() #' set_latte_path("/path/to/latte") #' get_latte_path() #' #' if (had_latte) set_latte_path(old_latte_path) #' get_latte_path() #' NULL #' @rdname pathing #' @export set_latte_path <- function(path){ if(missing(path) && interactive()){ latte_path <- dirname(file.choose()) if(is_win() && str_detect(latte_path,"C:/")){ latte_path <- str_replace(dirname(latte_path), "C:/", "/cygdrive/c/") } Sys.setenv("LATTE" = latte_path) return(invisible(latte_path)) } else if(!missing(path)){ Sys.setenv("LATTE" = path) return(invisible(path)) } else { stop( "If the session is not interactive, a path must be specified.", call. = FALSE ) } } #' @rdname pathing #' @export set_4ti2_path <- function(path){ if(missing(path) && interactive()){ `4ti2_path` <- dirname(file.choose()) if(is_win() && str_detect(`4ti2_path`,"C:/")){ `4ti2_path` <- str_replace(`4ti2_path`, "C:/", "/cygdrive/c/") } Sys.setenv("FOURTITWO" = `4ti2_path`) return(invisible(`4ti2_path`)) } else if(!missing(path)){ Sys.setenv("FOURTITWO" = path) return(invisible(path)) } else { stop( "If the session is not interactive, a path must be specified.", call. = FALSE ) } } #' @rdname pathing #' @export get_4ti2_path <- function() { if (Sys.getenv("FOURTITWO") != "") { Sys.getenv("FOURTITWO") } else { Sys.getenv("4TI2") } } #' @rdname pathing #' @export get_latte_path <- function() Sys.getenv("LATTE") #' @rdname pathing #' @export has_4ti2 <- function() get_4ti2_path() != "" #' @rdname pathing #' @export has_latte <- function() get_latte_path() != "" #' @rdname pathing #' @export missing_4ti2_stop <- function() { stop( "latte doesn't know where 4ti2 is.\n", "See ?set_4ti2_path to learn how to set it.", call. = FALSE ) } #' @rdname pathing #' @export missing_latte_stop <- function() { stop( "latte doesn't know where LattE is.\n", "See ?set_latte_path to learn how to set it.", call. = FALSE ) } #' @importFrom usethis edit_r_environ #' @export usethis::edit_r_environ latte/R/ones.R0000644000176200001440000000061013437126720012655 0ustar liggesusers#' Ones #' #' Make an array of ones #' #' @param ... A sequence of dimensions separated by commas #' @return An integer array of ones #' @export #' @examples #' #' ones(5) #' ones(5, 1) #' ones(1, 5) #' ones(2, 3) #' ones(2, 3, 2) #' #' str(ones(5)) #' ones <- function(...){ dims <- as.integer(as.list(match.call(expand.dots = TRUE))[-1]) a <- rep(1L, prod(dims)) dim(a) <- dims a } latte/R/tab2vec.R0000644000176200001440000000243714263603733013252 0ustar liggesusers#' Array to vector conversion #' #' Convert an array into a vector. #' #' This function converts an array (or a multi-way contingency table) into a #' vector, using a consistent ordering of the cells. The ordering of the cells #' is lexicographical and cannot be specified by the user. #' #' @param tab An array of counts #' @return a Named integer vector. The names correspond to the cell indices in #' the table. #' @export #' @seealso [vec2tab()] #' @examples #' #' a <- array(1:6, c(1,2,3)) #' tab2vec(a) #' #' data(Titanic) #' tab2vec(Titanic) #' Titanic[1,1,1,1] #' Titanic[1,1,1,2] #' #' tab2vec <- function(tab){ # if is a vector, return if(is.null(dim(tab))){ tab <- as.vector(tab) names(tab) <- 1:length(tab) return(tab) } # if it's a vector already, short-circuit if(length(dim(tab)) == 1){ tab <- as.vector(tab) names(tab) <- 1:length(tab) return(tab) } # otherwise, rotate and class u <- aperm(tab, length(dim(tab)):1) if(inherits(tab[1], "numeric")) u <- as.vector(u) if(inherits(tab[1], "integer")) u <- as.integer(u) # create cell indices tmpdf <- expand.grid( rev.default(lapply(dim(tab), function(x) 1:x)) )[,length(dim(tab)):1] # assign them as names to u names(u) <- apply(tmpdf, 1, paste, collapse = ',') # return u } latte/R/genmodel.R0000644000176200001440000000710713445172757013525 0ustar liggesusers#' Generate a configuration matrix #' #' genmodel runs 4ti2's genmodel program to compute the configuration matrix A #' corresponding to graphical statistical models given by a simplicial complex #' and levels on the nodes. #' #' @param varlvls a vector containing the number of levels of each variable #' @param facets the facets generating the hierarchical model, a list of vectors #' of variable indices #' @param dir Directory to place the files in, without an ending / #' @param quiet If FALSE, messages the 4ti2 output #' @param shell Messages the shell code used to do the computation #' @param ... Additional arguments to pass to the function #' @return The configuration matrix of the model provided #' @export #' @examples #' #' if (has_4ti2()) { #' #' varlvls <- rep(2, 2) #' facets <- list(1, 2) #' genmodel(varlvls, facets) #' genmodel(varlvls, facets, quiet = FALSE) #' #' varlvls <- rep(3, 3) #' facets <- list(1:2, 2:3, c(3,1)) #' genmodel(varlvls, facets) #' #' # compare this to algstat's hmat function #' #' } #' genmodel <- function(varlvls, facets, dir = tempdir(), quiet = TRUE, shell = FALSE, ... ){ if (!has_4ti2()) missing_4ti2_stop() ## compute other args opts <- as.list(match.call(expand.dots = FALSE))[["..."]] if (is.null(opts)) { opts <- "" } else { opts <- str_c("-", names(opts), "", unlist(opts)) opts <- str_c(opts, collapse = " ") } ## compute/write 4ti2 code file #################################### ## format varlvls formatted_varlvls <- str_sub(format_latte(t(varlvls)), 3) ## format simplices formatted_facets <- vapply( facets, function(v) paste(length(v), paste(v, collapse = " ")), character(1) ) formatted_facets <- paste( length(facets), paste(formatted_facets, collapse = "\n"), sep = "\n" ) ## bring the two together code <- paste(formatted_varlvls, formatted_facets, sep = "\n") ## make dir to put 4ti2 files in (within the tempdir) timestamped dir.create(scratch_dir <- file.path(dir, time_stamp())) ## make 4ti2 file writeLines(code, con = file.path(scratch_dir, "PROJECT.mod")) ## move to dir and run 4it2 genmodel #################################### ## switch to temporary directory user_working_directory <- getwd() setwd(scratch_dir); on.exit(setwd(user_working_directory), add = TRUE) ## run 4ti2 if (is_mac() || is_unix()) { system2( file.path(get_4ti2_path(), "genmodel"), paste(opts, file.path(scratch_dir, "PROJECT")), stdout = "genmodel_out", stderr = "genmodel_err" ) # generate shell code shell_code <- glue( "{file.path(get_4ti2_path(), 'genmodel')} {paste(opts, file.path(scratch_dir, 'PROJECT'))} > genmodel_out 2> genmodel_err" ) if(shell) message(shell_code) } else if (is_win()) { matFile <- file.path(scratch_dir, "PROJECT") matFile <- chartr("\\", "/", matFile) matFile <- str_c("/cygdrive/c", str_sub(matFile, 3)) system2( "cmd.exe", glue("/c env.exe {file.path(get_4ti2_path(), 'genmodel')} {opts} {matFile}"), stdout = "genmodel_out", stderr = "genmodel_err" ) # generate shell code shell_code <- glue( "cmd.exe /c env.exe {file.path(get_4ti2_path(), 'genmodel')} {opts} {matFile} > genmodel_out 2> genmodel_err" ) if(shell) message(shell_code) } ## print output, if desired if(!quiet) message(paste0(readLines("genmodel_out"), "\n")) std_err <- readLines("genmodel_err") if(any(std_err != "")) warning(str_c(std_err, collapse = "\n"), call. = FALSE) ## read and return read.latte(paste0("PROJECT", ".mat")) } latte/R/attach.R0000644000176200001440000000060413440553500013152 0ustar liggesusers.onAttach <- function(...) { packageStartupMessage(' Please cite latte! See citation("latte") for details.') if (!has_4ti2()) { packageStartupMessage(" - 4ti2 was not set in .Renviron. Use set_4ti2_path() to set it.") } if (!has_latte()) { packageStartupMessage(" - LattE was not in .Renviron. Use set_latte_path() to set it.") } invisible(TRUE) } latte/R/vec2tab.R0000644000176200001440000000175114774757572013272 0ustar liggesusers#' Vector to array conversion #' #' Convert a vector into an array given a set of dimensions; it therefore simply #' wraps [base::aperm()] and [base::array()]. #' #' This function converts an array (or a multi-way contingency table) into a #' vector, using a consistent ordering of the cells. The ordering of the cells #' is lexicographic and cannot be specified by the user. #' #' @param vec A vector #' @param dim The desired array dimensions, oftentimes a vector of the number of #' levels of each variable in order #' @return An array #' @export #' @seealso [tab2vec()], [base::aperm()], [base::array()] #' @examples #' #' data(Titanic) #' str( Titanic ) #' str( tab2vec(Titanic) ) #' #' # convert it back into a table (names are removed) #' vec2tab( #' tab2vec(Titanic), #' dim(Titanic) #' ) #' #' # check that they are the same #' all( vec2tab(tab2vec(Titanic), dim(Titanic)) == Titanic ) #' #' vec2tab <- function(vec, dim){ aperm( array(vec, rev(dim)), length(dim):1 ) } latte/R/latte-package.R0000644000176200001440000000151314774756516014437 0ustar liggesusers#' R Interface to LattE and 4ti2 #' #' Back-end connections to LattE (\url{https://www.math.ucdavis.edu/~latte/}) #' and 4ti2 (\url{http://www.4ti2.de/}) executables and front-end tools #' facilitating their use in the R ecosystem. #' #' @import mpoly #' @importFrom ggplot2 ggplot scale_x_continuous scale_y_continuous theme #' element_blank theme_bw coord_equal scale_fill_gradient scale_fill_gradient2 #' aes geom_tile #' @importFrom magrittr %>% #' @importFrom stats runif #' @importFrom utils download.file #' @importFrom stringr str_detect str_sub str_c str_replace str_replace_all #' str_split str_trim str_extract str_extract_all str_which #' @importFrom dplyr filter mutate arrange #' @importFrom memoise memoise #' @importFrom usethis edit_r_environ #' @importFrom glue glue #' @name latte #' @aliases latte package-latte NULL latte/NEWS0000644000176200001440000000067413240157725012077 0ustar liggesusersVersion 0.1.2 ------------------------------------------------------------------------- CHANGES * Better citation. Version 0.1.1 ------------------------------------------------------------------------- NEWS * CRAN genesis Version 0.1.0 ------------------------------------------------------------------------- FIXES * The package can now be loaded on unix-alikes without a .bash_profile, .bashrc, or .profile (thanks @GrantInnerst) latte/NAMESPACE0000644000176200001440000000323313440610370012601 0ustar liggesusers# Generated by roxygen2: do not edit by hand S3method(print,tableau) export(edit_r_environ) export(fgraver) export(fgroebner) export(fhilbert) export(fmarkov) export(format_latte) export(fzbasis) export(genmodel) export(get_4ti2_path) export(get_latte_path) export(graver) export(groebner) export(has_4ti2) export(has_latte) export(hilbert) export(kprod) export(latte_count) export(latte_fcount) export(latte_max) export(latte_min) export(markov) export(missing_4ti2_stop) export(missing_latte_stop) export(ones) export(plot_matrix) export(ppi) export(qsolve) export(read.latte) export(read_latte) export(set_4ti2_path) export(set_latte_path) export(tab2vec) export(tableau) export(vec2tab) export(write.latte) export(write_latte) export(zbasis) export(zsolve) import(mpoly) importFrom(dplyr,arrange) importFrom(dplyr,filter) importFrom(dplyr,mutate) importFrom(ggplot2,aes) importFrom(ggplot2,coord_equal) importFrom(ggplot2,element_blank) importFrom(ggplot2,geom_tile) importFrom(ggplot2,ggplot) importFrom(ggplot2,scale_fill_gradient) importFrom(ggplot2,scale_fill_gradient2) importFrom(ggplot2,scale_x_continuous) importFrom(ggplot2,scale_y_continuous) importFrom(ggplot2,theme) importFrom(ggplot2,theme_bw) importFrom(glue,glue) importFrom(magrittr,"%>%") importFrom(memoise,memoise) importFrom(stats,runif) importFrom(stringr,str_c) importFrom(stringr,str_detect) importFrom(stringr,str_extract) importFrom(stringr,str_extract_all) importFrom(stringr,str_replace) importFrom(stringr,str_replace_all) importFrom(stringr,str_split) importFrom(stringr,str_sub) importFrom(stringr,str_trim) importFrom(stringr,str_which) importFrom(usethis,edit_r_environ) importFrom(utils,download.file) latte/inst/0000755000176200001440000000000015021466006012340 5ustar liggesuserslatte/inst/CITATION0000644000176200001440000000332115021465776013511 0ustar liggesuserscitHeader("To cite *latte* in publications, please use:") ## 1. The R package itself bibentry( bibtype = "Manual", title = "latte: {LattE} and {4ti2} in {R}", author = c( person("David", "Kahle", email = "david@kahle.io", role = c("aut", "cre")), person("Luis", "Garcia-Puente", role = "aut"), person("Ruriko","Yoshida", role = "aut") ), year = "2017", note = "R package version 0.2.0", url = "https://github.com/dkahle/latte", textVersion = "Kahle D., Garcia-Puente L., Yoshida R. (2017). *latte: LattE and 4ti2 in R* (R package version 0.2.0). ." ) ## 2. LattE Integrale software bibentry( bibtype = "Manual", title = "A User's Guide for {L}att{E} integrale v1.7.2", author = c( person("V.", "Baldoni"), person("N.", "Berline"), person("J.A.", "De Loera"), person("B.", "Dutra"), person("M.", "Köppe"), person("S.", "Moreinis"), person("G.", "Pinto"), person("M.", "Vergne"), person("J.", "Wu") ), year = "2013", url = "http://www.math.ucdavis.edu/~latte/", textVersion = "Baldoni V. *et al.* (2013). *A User's Guide for LattE integrale v1.7.2*. ." ) ## 3. 4ti2 software bibentry( bibtype = "Manual", title = "4ti2 — A software package for algebraic, geometric and combinatorial problems on linear spaces", author = person("4ti2", "Team"), year = "2013", url = "http://www.4ti2.de", textVersion = "4ti2 Team (2013). *4ti2 — A software package for algebraic, geometric and combinatorial problems on linear spaces*. ." )latte/inst/INSTALL.txt0000644000176200001440000001113513437561152014217 0ustar liggesusersThis file is intended to help you install LattE and 4ti2 for use in R through the latte package. On macOS or unix-alikes See the GitHub description of the install at https://github.com/latte-int/latte-distro. Essentially this will just require pulling down a tarball, extracting the files, navigating into the directory, and using the standard make sequence of ./configure, make, make install. Nevertheless, follow the very well-written instructions on that page. On Windows Windows is more challenging because both LattE and 4ti2 demand unix environments. In the future the Windows connection interface (Cygwin) will be changed to Docker containers to be significantly more extensible, lightweight, and easier to install. Nevertheless, the instructions below show how you can get up and running on a Windows machine. Feel free to contact david@kahle.io for more any questions/support! Step 1: Cygwin part. • Go to Cygwin website. • Click Install Cygwin on the left nav bar. • Click setup-x86.exe open the executable. • Install from Internet. • When the "Select Root Install Directory" page appears, click next. (C:\cygwin64 is assumed for this writeup.) • Click next until you get to the "Choose A Download Site" page. • Select any mirror (e.g. http://mirrors.kernel.org). • In the Select Packages screen, click the + next to All. Then * Click the icon to the right of Devel to change it from "Default" to "Install". * Click the icon to the right of Interpreters to change it from "Default" to "Install". * Click the icon to the right of Math to change it from "Default" to "Install". • Click next through everything to complete the download, and then install it; this last part takes a long time so be ready to wait. • Once you've installed Cygwin, open it from the start menu. Step 2: Unzip LattE. • Go to https://github.com/latte-int/latte/releases. • Click latte-integrale-1.7.5.tar.gz to download. • Move the downloaded file (latte-integrale-1.7.5.tar.gz) into your Cygwin home directory, for example, from C:\Users\david_kahle\Downloads to C:\cygwin64\home\david_kahle\ (Note that if you didn't open Cygwin, the user directory (\David_Kahle\) won't be there.) Step 3: In Cygwin. • Open Cygwin and type "pwd" and enter, the directory listed above should come up. (Now as /home/david_kahle, for example.) • Type "ls" and enter, you should see the latte-integrale-1.7.5.tar.gz that you put in from before. • Type tar -xf latte-integrale-1.7.5.tar.gz • Type mv latte-integrale-1.7.5 latte (this renames the directory to latte) • Type cd latte • Type ./configure --prefix=$HOME/latte --disable-lidia • Type make (this takes a very long time to work, so be ready to wait) • Type ls -al bin, you should see a relatively long list of stuff that includes count.exe (this is part of LattE) and markov.exe (this is part of 4ti2). If not, something went wrong. The executables are then made in the directory $HOME/latte/bin Step 4: Set the system path to include the new executables. • Edit the system path by the following: * Right click the My Computer icon on the desktop. Click "Advanced system settings" on the left nav bar, and then click Environment Variables under the Advanced tab (the window should be labeled System Properties). * Under System variables, click Path, then Edit... * Click New, then type "C:\cygwin64\bin", press Enter, click Move Up. * Click New, then type "C:\cygwin64\home\david_kahle\latte\bin", press Enter. and click OK. * Click Ok and Ok to get rid of all the windows. Step 5: Inside R. • Open R (the x64 version), and inside R type install.packages("latte") at the prompt and enter. If you want the dev version, see the instructions at https://github.com/dkahle/latte. • Type library(latte) • If you see a message saying that latte and/or 4ti2 are not found, use set_latte_path() and/or set_4ti2_path() to tell R where those files are. If you use one of those functions, navigate to where you created the executables. This is probably something like C:\cygwin64\home\david_kahle\latte\bin. If you're setting the LattE path, click count.exe and ok; if 4ti2, click markov and ok. • To check that the 4ti2 connection is made, type ?markov and run the first few examples; i.e. (A <- rbind( kprod(diag(3), ones(1,3)), kprod(ones(1,3), diag(3)) )) markov(A) You shouldn't get any errors. • To check that the LattE connection is made, type ?count and run the first few examples there; namely spec <- c("x + y <= 10", "x >= 1", "y >= 1") latte_count(spec) You shouldn't get any errors. latte/tools/0000755000176200001440000000000014322541412012521 5ustar liggesuserslatte/tools/ipCheck-1.png0000644000176200001440000030270213424210304014732 0ustar liggesusersPNG  IHDRx  iCCPkCGColorSpaceGenericRGB8U]hU>sg#$Sl4t? % V46nI6"dΘ83OEP|1Ŀ (>/ % (>P苦;3ie|{g蹪X-2s=+WQ+]L6O w[C{_F qb Uvz?Zb1@/zcs>~if,ӈUSjF 1_Mjbuݠpamhmçϙ>a\+5%QKFkm}ۖ?ޚD\!~6,-7SثŜvķ5Z;[rmS5{yDyH}r9|-ăFAJjI.[/]mK 7KRDrYQO-Q||6 (0 MXd(@h2_f<:”_δ*d>e\c?~,7?& ك^2Iq2"y@g|U\ @IDATx L/..}Neɞ !)k/**K(!!T"RY*E%?on;sgsf99~f<,$$@@@@@u=     ^     @ ҉     ^     @ ҉     ^     @ ҉     ^     @ ҉     ^     @ ҉     ^     @ ҉     ^     @ Ei6 e˖-鞳`rr\pl"k֬%K;=~ٲe=ϧ4_ E7ԏl\)=Y=_ K7<~i8*PN7n?z:ul3;wnGۏƎ9b*+Cq¾}6Cf/ \rW9{iS }-Z4..y*~_p`R`Ass̙3B8^f @T oTNF@@@@-@@@@@@N9o@@@@`/@@@@@ ZX3G@@@@@x]@@@@UoF@@@@ uC@@@@V:s@@@@\/z@<(K,իWˆ d׮]r1ɖ-ϟ_ʕ+'UTFIf$w!B@@@@^>ERΜ9#L:U.]r<|Mٳˍ7(}1gɒ%7@@@@ECf(HJJcǚr QܹsCRfM3gN,G@@@B @-ԩSGyٷo_n:֭iFvܙ@@@-@@/lAY… vڲ`>@@@p^M6CE.\ >i~q֬Ydɒ    @tEG7%X)pY`u}իWgeWZekT   / ? իg[N j̧2)R$2e˖5P7lbIEr=-    @ xQ"Q.#5Çu;_)o޼)7de}v>ԋ%%%ѣG}>zߍ;vx:(ɮoDQ3O# .O:%$._nYF࿽?33sz9H s֓_y~# -@[ ` WM3ܙ3g;}1+USN~;˗}i\z;8vȑΛM\ЦUjqo)B{7/t;ipܼQuf| t ^dM_yW;ϖ-[()5+@@@XQ/ QMT*VXz/:fu}U;UTd 7jjF@@@`E^\"Pxqѽi+۶mKwk׮5W^=ϻnԨQfnGAB@@@ 9\*_ylѢ9/2¡Cd 9?3j3:(%JQ5u"   @ d(X)p-}oT=~uԑU .3g/:j}UbZ۶mm9sUv-sP@@@\!E\1 t6m_|!=4mT-*+V۷F 9sȺuW^yePKwq̟?Z/ѻw @@@\)@וΠL+WNO./N)Tvm3[lٔcܰ@ $OΝK/͛7<]v+    @ 9d-0`џg%i^dΝrA)U+Vg_PY'rCg婧 w7h@@@D=xd&֭[n}@gϞ\ wzf͚#   @ `[oe-lKPF >|x'9   #@7!;t)S0v:E{=ɝ;M   D(< ^{5+Sc9?jժ)@@@@ ޴&A bqY'2_ϕ>iH8   ~ ]wϊ+dԩʞ={\tkJzp\Vle4țEs(a^2    {=)иqcџ.V7ʎ;Òq)/T-_Aլ) 1%4@@@p^M9FV*ѣr[$$$H|||a%o @@@`ޘb,<{@@@oL  @f   Ĵޘ^"@7Vfq    `^k= M mT   @ ک Fnuƌ   om8DAވ:   @XF@ ͜@@@2\'@uS΀@@@H#@7 @ =sEO@@@Cԉ8(@AlB@@@ F؄@ Q@@@ s@S /@@@'@}sΈ@ 24@@@  @h ͳG@@@Nop^FB oTLD@@@ x3MH @d yW   X)@JMB"L oMA@@@bR iy#mF    Β@ SC@@@ȔLQ3W@@@@*E>@ $2@@@zappA^72cD@@p^4Dzap@@@(u@ ,.\Q/^,+W 6ݻĉ͝[ʖ,)Uʕ/k4*ˇ oPl;z,_\֭['[ncǎٳg%!!A-*+WzI:u$kV>KL   X @D@w۷O^{5:ul߾$&#Gd2f:Uȝ:Jߎ%W|ϲN&ȫA3feŊaw ( :uo]7oa~2    @p, ΋ B'O?.ʕg}opO*#(ߛPpW]Vh]Gʖ-+ o61SL-ZH dx[=C@@@x:XdT1Vߎ3FΜ9P>,-n-ws3?|pstJh׮tYTEY@@@[/@u[l)v#ú}C=KCA?,-%ta+Ӈ~(kז4v+G]   8)@ImBnˠT+8}J:|Tc^ 馛_|to֭@@@@ p- }ba+wq|G!Ѹ]O>-@@@@ V2.I`̙:4{ې!v&'MGǎy_9;j@[n믿Q=u"   xc~ *m6ׯ_-wXzOșg-7>\2`XW/^קO9u%Q    n f W'Nc ޷ߞbg>>~;jvؼyKv7C   ĜޘR,^XϟJQKˌ2E:x:칷ޒ=ն<&L۷V?#   xcqV-0bĈQ@jxvT#Ǐ˸ٳ|wĹsdN5G;   ĄޘFشi HIo~4O%9֝~*#d۷~[NE@@@@ 09 bX`ƌ5G+V8֧ >u ͝;7lG@@@P@ |gTѣïF?쳈A@@@ F7]̙3?N ,]:"!槟B*ggKY=u#   Sxcj: +yf9|lϿavp۶6m`Νrܸ @@@2 9@ nr9{V<`?wF( l۶-bA@@@ux]7 ;}7n=q8F(8j LB@@@flDaJHMIl٤DW(c    v S@ "yr޷\mo#J1    :rEQ(`{h#A-Z4bA@@@ux]7 *W}7bn-XP'䵽?Uʗ`Ȟ=/_>bG@@@x]9 <KB yF:U8җ`.rɖ-[0Eȋ   kv8@,YyѢ~}GTZuIYh‘    @7f1 @:v옩vp5vTθ8Ν;yF@@@ FtYCK.;V^QTXю[7ޘpˤiӦh6@@@JQ9mtHHH*3U÷ݖnӸԺ`ْK   ĪXYƅA h`1W\A#s{6vTN݇xX˖-+wq~r@@@ Mkp%\"O=TG$[lsr]&ȑ#%Gއ    G}T5jEZIyJ KZni@@@h ͳG@Rٳ̙3p–HeuTyRŊɌ#% 4ѣGD@@@H%@7w@=p,X sv BRW%>gNPƍaDu"U5.6؉   V Z@ tE_~) },*Têa_v2QXlgZ5zD)zP7   1-ӣcp :dIJJGfjիW J޽eݺuWE^rȓGN8+[X5V~kr={,Cv\Frp!I.R$fyG#B}{S[~{N:%n%/xRln笖D7}gΜ8J.mnþfԨ Ð>}̭~j?AFM}[#KX)^\0@kgv,:o%J=x$mS~{s0d i99L ՒS[Yy} ^ Sٌ Kq#hU0aw}O˜9s. F|ҿM2FҖ Ơ0H2j[2l++G{;;tCtqIڷ_ M~o>>#.AK:p63#Gm3>|PhѢvq sV  =p(P|\iwpi@Y'! K/#^5jԐٳg֭[eڴif_ʑM}1ިfMuruIaMU4ʖO yD_X>[Yz;t(kT(-;h! hWk$ț+@@@H-@7@?СC]9rJٰal߾]<(ُKRjҠz I0d?!ٱc:dumn9z$&3ƚKAJƊq] o @@@ @ f20@@@P@i1= @@p^?@b_ o1#D@@*@׭3ϸ@ uل3\@@@%x]2 @@ /@@@X k3x@ I@@@(]@ .\ G{H΃x,qCh7-Q⟃B@@@ Feɓ'O?E/6lӧO_ԩ RBviݸ\۠d˖<|g֭dJmVٺO9z$&9a?gΜR@TԬYS .S   %@7 3f̜9S4/isڵϋӧAϾ;C=zHтs@t#XHʚ5\۰iAjqA`ǎ{OfϞ-˖-KOQV-СKT4@@@D=x-aeƶ Uɓ3 g!y77ĤECGʽFI;$''+ǐ'M]dG3ړ2x`)]u]_dA5#F07۷UVE   @ 9d `4;i$ѽv3N=+0^y߶-^}c*]:˄9Iҹsjo6=g. ;Rree?r|4h@9\@@@H%@7w@ / ]w8psȲ߿m" z˗[VG^zQ=4VZ4-s?[Ym5}={Z6ĉ~0    `a#G :sF:<*HJϟ=D^1ön7=h{".Ac6I۶meʔ)_/׬Y3Y}[M    ്@ Z^y>|#?oi\H{4r2ؚt&1Qn40V5[dɒ%ȑ#fy͚5C   /@7"@|<#A|V۶'"b_Wf+o~Q` lO))VXVO+跧A#4x`IJJ W   xx:X'0n89}uXo[ȂC,zQS^آv/9z⸌ ؐs2c jJ@@@X 3@ C]1;u 9a';Ք;þz3t/O<ٱ1   @d$ O?$[n >YLE_Z?k\+jL|̘*f    F f遞9{VV])[-G[ dzPTFQ(v:@@@ k'!@ ^\@1Pտ4k\.uXYgr61g#(؞P@@@1QDƍ#kn99,G;%BFصN9g4f 6xn@@@D&eG9H:H;4s}wP0]=}lo@@@bKol'AN<B){8uӎL#N'"/   B^ Ggӡ>Ȟ=drEsqA@@@"[odC@+5/O ;BB%+d k@B9! "    u@ 2*VqX#}*Sds@Tڙkl+WT)lA@@@ Eo 7@իWרL9[lR|9kFX@VZ5t@@@ FCYk૿n XWXҞbND"R\9{B͛7E@@@,@ͳ@o|||hԩRE.X]̱2jHLp:3#/WϹ#@@@NL  ƅ:w1y};GҺQ#G׳c׾]r\Ϟ=%kV[v @@@dL$@ w}yr;ڷ}xﻹ{`m̕3{vM6~յ.LZAp#1NF@@^of@hڴl2#Эʟ~f)/z7x 74h6~I2eRs@@@@*E>y_~Yt5kR c!w KʨKh޽~ڵ]9l#=|p]~#   ޠȌ,PV-+7^uEu佈;   A   >Jۍ7ʠA$O:y'H5xHϞ˅%p @@@ @2p@#9f2dWW.[LΞ=뗦 er ͮH܎>?!$'Nͣ]tiuޡA $i܍D@@@@S/@  ~?_[%RnV,SZ+UW01t3+4nbdٵo=qB%IB-!9\ɒrgǎZ@@@ s@&9sJcu=zTN?qȪV/VXqZ&ս!G@@@؃qrD@{,   ?x #@7b   -@7!Y g#   o`NBU-[4,YHʻϸΝ;KE/dFB`O^    .Xf 6,EΞ=[f͚71cI&~p uی3^@@@ p[˗OTw[n$)S|'7md-]ɓTm_S2p u3l@@@ q7 4h@WZt 2Dr-#F-qOwȑRB49,   F.YgdB`׮]ZMO>+W./9~Kٲe*C&H+A^ٻ7   R+A#?/'OJ暀+޽$[l## țք#   @{Bux=*ǎK{„ u ?s@w E#ŋeժU+W.y衇* ޾˗.Roݺuٳr y… ryy8mz=mGo ǼE;%91I$? nFlpnyyoFSK}?ܙy{$C#9f`Ɋ:Bm;rSN{L.\(jպ~=D$@[wG7Qƍ3vM+*5k䣏>2/]QFKѢEȰa(_  "+:uJÇ/W%x>s4h]%Jh}/tm۝;wy!i@84Y|饗GO06!tHXbF*k֬ұcǠ nٲE4[~})P[N>czKrt@Y* @@| |… 3]ݻh]5KEH 3C0y=j֬YЫw%_|޽~t=etm۶nA  ;wZR~RΧ'OKRN%Kկ=II x6[f5oO7KɒUꧏ=c/7i Ns{V9U=笧Wy$ӿw%.yjp1gϗW_}}N{ѝs `^ۉiؿ ^M]t z@9rɓ',|2}tꫯx;t +tM `U_z@( Ǐv*T  g[}p"%JQW[ͽݭ9"O6 >2ږ(c9/NJJx>gϜ9cҿyNip7?zMhXf;?pt=hέ;v+SLT}ٱF!Y%f!Q|*rW\ak׮m֫/$h-T v낑2D@F={H߾}E jժ#tݮM$'J*IqRJuꢑ[jժ?w<_|jIW0[dr-7|S7nl~Y U_{Ŧ=yI>)uAS{oayX?dM [k={'cOR"#xaW@_|':wl@&mkp5HĨAX @ 74ة?3e4V+HZd)һ"瞻(u{GziÆ ?$uնd--Zdx9xyL=tC5NZFǦ[ލ5*唖> {O-JY@IDAT?czO>xYQ޺ukkq KjO?yɊ{mp^洈@T 苊lٲeH}_f裏4Cowyy_ѕzl)һ+5ȫ?7J/6myJ[.f/; ^iK (   za4[W?OK &HM!ycyv #['7{JÇKÆ EpUWĉ͋-twAWj W3`.&3gYN$Фh jN:4.b5Iڴicy饗.Z=g͚%Ł͛ˏ?h֡Gho6sz^7zhi᳧eB@.bŊW?M9sE{K]veSZ~ԩS)u4{ʕ/L$F 5Ԃ  L:܂Ak\sMK:n H_(HɣKϾBvڵS~8\2eJo?\%Ad-Iڿb kҭteofYKL/O>ebUް(#BhW?57n!(ʿ>ya]_CO5__}15x`OI `A^, @?r~H}^z>Ěo)Sr^o5hEp,EMM4W̭/Ŋ-9s4_i]ey4e=3bqd=u+i"]@TBLuU_{ҫ._܏J+=b  2g #@͢g-LD@lX~Y %j|[Z5Ot_z)7nܘr icǎQti=5رT+Wmʿ/Ӝ۾}{oޝ9sy?O<ҭ[4U[14r" ް(DݻeٲpB璢E媺u:J7V/b!MLeƋ%VZ*[U Gz<~xR|9ih\aUFRo-#G#aסCr'.gR !\jVre mٕO6/(r1 D޼yE$@@#PV-M?~<)S\(Lk.iEZ@鞟8qy\+}P+V[+^O/v4>z[ѭ'-kx]'|"yN9}3_SdqC/Ȯ]̽]JBBBRV=M@ ;"@4 |2rH̀VFcm|}l_?{Nzpg^Po}]OՈ3J -Z75kf=, ,X 3߸x`7e:u}@B@ s=2vXٳgoO7 '}]J_}hgϞ_~mjf zz0 &{6 {;bsZg஧ߢ[<$4=i$ϩߺYܚbquI9_CI2XVNo{OVS@ |l>{ZF(k|GҸqc3'gzo@E|59&/cϴ; j]o׍{ C5J*th/S>PpW]8ux~yW j?m9ۥ;cHLmנ+t%\";vɓ'எO1c>pz%l}s! S@3fszQ/]U\f>na|0l{;Zn颫Uׯ_o+8Сy_KxX`hի\yf>L5k&ܹsW_n)X 4t"͛77ݻ˶mAmڴCXWj; 4x`{9oE.֤w_Ɋ ^i P@_4V_zVdvI QSޒ{:_>X JjPӀj%{>g@t,͚enAjG^J3r:s:jl++;wec ]r 9;y⋢c6*F@[_}=H^AO*]]mZ֓Օj^ogt5n+xuƶhpՕzVovje˖YGz'4hܴiS~sAxmٲhYϟ*7|,\˗Ϭ[ۡI-N骫J j/_\n6[D &^{ B (KV_CoL  &L0fW:ip?Z]e{8 s]*5*Zl\L>ml7tƀQI!O!cEU>h m3Éb(C/C_Hȃ xgU 64Z- e˖ɣ>귣|7_-Bk]@իS.6淢T'um_x֤<%hjxڵĸFzI+gjv5PBt3JѠ0.ʰWEA;}GfL^ci+zkBlm3ʓ%OÌ+3%t2+_n+V7?ٷ﬿؇O/^9Sq:%&&O?t .-"r3gya70Lp^L4Doʕ39pV"4i61qp-CG /3=,zalqp$/>c *;m" @l ԭ[W.\(o}TNb{Ќ\)@וΠ@ yA/ukWCu/|^c[o[T o8'˖-ձ;:m" @ ,XPZj%}6mW gxX'#?)O{mh)&,_q&s|ݷlqW7eļ_[PKI     ͍R Clڴ)bFl{.]l{UuɱsYN_ZtiXA}49   ތȁ1.~F}xm1?j\x緭[mWcg mݵi[l=LްaC0Eȋ   ^  z۷G{vcHJNؽ;bgIc!ۄD̃     l Ǐ;y±>;qұiɱk;=5cyx@@@ T E DR''_H}ȶ199vmǚsq>|.~$>ÆA   @x"+Ħ@޼y#n`yvO k+A99v3ț;Ӗ˗':C0r   xԦ-HK.$Uh1Tsm2('Ǯ)],r\)^<)q$O2eiF@@@X k3x@ hU] BEuW-_3+Y.TP|55kVLY_m9 RwF0@@p.D@r$V6rGm]5ָV-@YN6糭իNW׫tiګ]wC4   ξb(-ЪU`FKTlSЦcWM:Mӏ^Ko׮cm   kxcmF$УGY]([l- mZ= G?.5~mXfHm_oeuk%>GۑW^vTK   +b$d$+x+D^F.Qw-?߿KǷFH=6Iݻ{nuMee3| ҷS']_wuRZ5ۥA@@@ VL2Ȕ}'2UN+ JȭF-[\'Õ?\M>~+ jO?tXN   @  `Fpqp^7 o%EǜSH9`Mmq{vehu!7+l(.2;vl(E)   %@  &5jYfw ;^N^+TwsR@pl#JcVq玏9cH|"bƬFIҥmO?y   .@7g!@{'rrmÆ䧆J+6%K̳ruz! s!_u饡VPsAw*~Ȱpx)%5ӧKmk@@@7 ul3VX`ܸqy59rWˉ9gy/͛֜1{hަmmZq7&x.`Zx|m4.ZBRoIÚ5-o:x٤ؚB~*D@@(@׍Θ@ C6a„ ۲'>z%|pgϙS7V_4meաkҺt~?AǂUI/fƻg c_e&>wJE{RAV3CWhv®y0A@@W XՌ bU@kX|\nJ_yrUW[U-h`sh۷ޒUflF}!?;3&Hopzѽ_~:-C7ߔr%K\]F{WhѬN]џf{ůkeCfWvt]4 )^p7Muk9~m.9fNN y@~Y#Ha8D7-"   ؃{ _ݶufjM6$n>)Z\j8 [_4#={?sΙAĤ$պIW6_qnРF K Os   om8d(Ptiџ ȩG%n *V$ݫ6na  ΋   q #@7b  gk<,\P6n(J*Iznݺ~{gOe֭RѸBӦMq b 랹f DAި&:  |ZSnW^\W_'xBN:uQٳ]‹ p @"\@b\ IJo6;vYfu~hѢ{I.]1L>]xѕ=|g2n8s,_}2U)Vt2@bG3@+4zj3YztWZٞu {k4ղeKڵԮ][;y7_~gʠA'NL9:w,M4%KCf>A`ol/C@ XG@T 99YFil+k%KAͽQ͟]vɺuLgy&UٲeW^o&9s/:B YIq4a.v8p!8% $$'{pKpw '˲~<3]UoTWlqGvs z%Jqp@G@ף΀Cl3,A8qnx TTw7G4vO|yܖbŒm?O@|M*e<@z%&zlWo&ܝ;wxwMRu\s(|g.='N hԨQ#=]tD3mxA#Q``%x(x=tbxyi+XkٱfӦMAڟufׅ֭[ӏ?HׯgϞ}VgY/g>C@<"<U   82iӆZh!Vq WYJzt"uls̑[>G'[9>p@@2yi+7So2k,5Kǎ|/}Cw?o>찿7 _A@@@@<:p Ǐ^5gϞ Җ-[ĉ>KʢEJEr椪ŊS*U(yĖݹiter {\b#zt w4 9sQyk ݹCN7n'\GF T'K*=gꦢT? & Ei(eҤMm-I"%;cq*~~2 3qmi>5v]siw= hQ??IUZ57V,rC@R$C\rvMǎWғ'OիWS82d R2e(uF   `@ m۶ԳgO{Mq@@K AS ԫWO OxOzEk֬QDKÆmSdASВ["enxhTU#-/<<޽{Gcǎ8gOihuV 1ݺS9\ngaqfK` d/!fk]:ԫE J 3]5i+&JDMʢN\t)M:?nEnݺt2[jnu=&2!`~ڊ'Rb\"a܋_sO܈*VA'BV),z㛇۷=z8n4Zxxj,x>S`cjܸ1=zH"̘V2{,J0Z_aJuo܄~ q%HCqCi~Eґx"pQڮN x_*X!=Otܹ:wL.\3OK .\ؙno8{%~R6g~C'Ǿ9Ύ[Mb5Jq-Xeqgf4ō:P7-A@v醳 XhU\9Ǥ3}=#zk݊;gn'-ZH5z|hp[7G;}:Xpuxjߎ?(zM}'MZAA\(d Z}GʕTpbƨQk ڀK K`ժUԬYxjJ]:YQh2~| ?^5͹JZr7q?҈gb3g7)3ppA4n<["6&ܵ)+0 yy\eر !!/Ulp      8q5iDlPQXnP s_\y|63q+]õ}9zNuVgŋU@tMi_SUeN%oGd[3v|>G\Kn7AصkFn +ϟ/mmi 6tT\SQFZeܧv#Fÿ̖˷nףGiϞGi5S ۏe*aԯ+VW)11:D(S'ۦ"'/<2oLׯR%tx(x=tbs8rܹuR5ldTnWzMtSLl,n/_nVv>;ʼn[BU>Jsp9 {͏rzN^s<[ psE     I^7X  0c"{(rMyuZRx9KU=w ZU ~YG)Й3zp􂾯: A@@@@@~O@%ɔQҭ[rczⅦ:)|[[َK7i]K-ngŋu     O^Cx `FQf'֡}S[KZ:9=tZrH/;kQHSMi3uÇOq      N@id ^ze^ԖW(O ;-Z}5|_WϏz̻_F쑙@@@@@ ^kAT"3fLFv~X1Zeϻlӆѣ(tyE/x_q`D+8kϖEz?-4X';$H%N$:hI$5,8   `B͛7aڼy3?~޽K޽ Rl٨lٲԠAJ4I/w@w3C SLvZhw9s)/qcT5eSk;ۑ%Mkhz^yK )Sq,Y4   N>|@gϦSz~#GН;wtyZr%u֍RJE=zbaxxi+UzM fZ%YFٳknF IÅrʇ> ̩>KʊφB:L+V)A@@L-\LJ,h~qTasl|A^euï *䃋   n޼I={8 X_⿱ .t:&}ŋ5޽{4sL4h?~ @<5@EEt]nJX:lְbE|pu hlRf+үB¤W(QPJÕABD\Hb)g,gͳuF   a^xAj"*߿VZ]B~m۶onӆɓ'Sƌ]v4zh1XTvm A<5@EEغuk{+׭M H\l}2He3ZM>~r(^< ;֯/YlHtmH/z5džp   ޽{өS;lhذ!qFȑ#iѢEv]`u] r/o>7uTVujժAnw@;^8@7fs:Mrd@5JTgpFԶi5mZV:;0_ԫE Z*߄NĈl×: +M,U Kie]lܢʕ˜Wg\xf̘Lmy3'lclg͚5iȐ!vy5Gj7}t3fsδw^J#66l;xx=c cCIuP 0EWߙyPf!eJOWw=4lnj~T2`fZӦM   Ǝx);xaݟ3gȑ֯_OI$v>/_Nߧ R˖-?+YdR> w3p/oUZ cp'TǯjlD-%ѣEÆo|t)P@+u6  d H\Zd|6i!#3W.  X‘N ;v8G *s>y>}z5Vh+˾$' eyⅵ&8 AɄ+ [T+y,F˟-=reʤJ ء^="6fHGWt)SΙK\үU+)ØJNyL׼α+k1(]t40х;sΜ9Rr)#PPf|sA8P&%H#yø86Έ+\n%@(|b#(.6>h61kr Q4k%dzQ*U\B~VNӖ-W_dCB$#,tIy$:g."HycF+~Xp6x-(AܸN5Bb#c,bSI2LJʉ6j%JXA^@=$x ԩS敚c[2rJKkZkɤb)44Oy6[AZ@ 3AT'ϟO;w" qӦMN%-WmPgD"r!Իy `>-ٲ|Iҥb߶P IرG)9Ƚ`F:{]7Cr]:TPuvW9%{ƴy)عt=.%ϥ#\Lb;w9KnݿG[Oś7ؑ~"(X%MZ*;U7'"vȓ'E}޾}W-ڵkK:gϞ/0oppsx- fp\p.aC'o$PhQig[<(=޽7zE_J?7: NfIV Nݛ:L;SW.ӕ۷)3z #.iU镊wI,6 G)p㆔+iôqRT(јuyHTߨTSlXz;@IDATnĦO_<>gḬ.+ҮN]*Ex?]B .%TW*27-I@$W% >DdM! O^ϟcx 0Ӑ!C] .m(pfgypF&gg?oNo8"n%':_uf`wx(ekC25̞=;ܹS)X!rNB#q<002x I-ɁK 'Kȸ~ߝZ2UK9k3=1k 8Kﻧ@@$\V).M >\ 1N֭ׯgb%,\P:9{ 9   n@A^7$  _~;~xJ2&vk$k֬T]J ҥ >B99sEi5w@;^y``"2 .]ӎ;JP Aaä 8oOlpۧO/ WB׮]TaJt%@@@>% < @@; To۶ڹCiӦy,q4n8ZbEFI&MXPs&8    Ec$w (H cǎQiѢEƛqY;=ɔ)>|ԩSRF/3 aa w@@@<2y=c@NxӰǏSN(mڴ 'NU-YN<Ϝs+.Y$ʕ ]x x"dz' L^F8  Rti){(~|lJ˗[3&ŌC+ pz  k= 'pA?>mܸnܸaޜ3Rҥ5(S6ۺG!!jNq0kw#̏;6eMMUr _x΂?٫WituxGF ƕ@TRX(mN%J$ 1VX'?Μ9C퓒+zC@ ԯ__ 6@(QfWX!L֠fid-jHCCĉ4oHK D-WlgϞ[Q!a„]S_荰)'/MۗrgJw}8spIxlKbY]6Z2Y?[xaMZk'YD`Q)[ +"2.>),eh~e˖ݻwmG5kFm۶=L߷K88k3{$nEJOYNMky{{~φz,z :Pݽj"o04h=rcǓ O'9kf=}.9BP"j͟G%ڶ{#UTqӤIK;v(5_ 6cs4l 8] ^o8KoVVuRp͛7O=p@܎n7e0@@+;v젲eQcVi9*7sUo&SJڸtV*u)J5gZ*+e~;}:ۇ܁W^];ED:zҀ)]r%Tj$2sC$׬)-%^,Aޅ R֬Yi(K}zZnUZ+\KI1{u3a%.]jwcRѢE27L/nc#F iIpBLOr8{,j (.6>|ڪ_Uq}Yo#KϰA?  *dJ@A+NfժUq7UebI2%eɒXbY9r58)S&8p 3jԨ!ׯ,=39pmN=3g]C!"ਇ S~V=uw̖5{y"z~PўCaϟӔK5S:ʖg٫Wim)v}ĈTR& h"Yxfy* dɒI5KSh,J^]C7ڵk['O.-9v[.xNn_\\ATR/HŊ#woL˧]&DWpzz3 ԊgX+vltIsΜ&\Ok ]&Z\zK6A+klݺUSP  `l\&M+8oD޽{%=[h>٤I] :Nuځ&MJqđzs.?~ .n7w S2df>QF3fL/[gt|h?MY:yyR![UMZU_k˪_3ȺRڵ^U/߮]֬5xnpk-K ־CoѩS>='O=zT:Ր$C +է2pC?p@ٲee9Xʕ)J(RӧOS^(ׄ2ٻ\NAUn;w+VlѣSɒ%Z޽75ڲϦ>s*%}{N=[߬LQ/٭󊆷bTʬwO~#gxCƐu   /5.u- uoZow k% q@l@\pjӦMSy9иq ^K_K:L]v%NR]Gvfb5׬:d… ڗ9Kٸ^`Rq֭|gqh(=׮6BgpX}|z zwE>7\5e}%ӧP9 E  x.jk-/Dy.-[$JȪ:ˢMV &xpC]K͛G .|59rVZQ) @sO/s׬Yq &Nخm!"?~|m2baE[{l@B[W_̩h) |ϕ1˪!|zyqsBm6[vFY>| U;0Z sWPlٴv=B7">帎q6)~:Jm>>3'pQA$q*;=+y}ZrI8Wj!kGcIiR{GA@Esرc s Uތk0ӇOժUvX^z%8p8[@)@{9Zn:t={6$/7U5{?8؞e˖Y'mڴ쯜 XGvphNm=02',MbZ[َg/ FwW5mIXh}7ϙc=2M Q`Ms8Sg(ZwZ14p \# k^z/grI8qh@\~ 0]VX+. P}{BST)Cƍ?)c_t8Zvmr K.UsW%#UJٳ'M>]Mp=ofڏ7Yc&=$u94/h;a!NM?MnzNc^szͻg7A@C7˜9eϞ]}ɓ'JMk"_/&8 v ."4u p HcL>M4R.osLcsaÆ;w[mSklybŊIg>$3f̠Q,a]7$ILcԜDҐ}g⋛t6$Ms\?%~< u>GD_󬗳zME$6jS8UTNVacoʫWu2gϞI sny+q7J.ٞۄi!]D^I!  *x]%~  L?/^d$dWnݚʕ+ݳguM;j(RڵOyW^nLɀ%;k<dΜ9/9#Z;Yf5?sQߍLiR⯹Ҭӑu2/ROɖ.Ӿs4 ;/c&wzI Hof2FwWX5]:kT=7$8{ʕ׬i48#4<êi*Pro{{9bx3zLO֯__Z%u֭K=-9ݿg8@AAA;x\?  (}:jځ7\ڠD!C2dw)B+ݻwO /_/%Km۶EdmذAW:r u -3x $IXlb##|q"ZwnLolf>hR~[e8kԆ:H"ŋMSϜD:-̔:5tzJd03gN̡9x1Nlɘ1&kMN#nP*ͶY.UW *9 pN:,Y2ԩ۷OK\߾}H|WCdg˗O| -piСZ̙,l \kfklIN>-֪ \o85^&u󐯘#=A/)W^% ꫿|BK]Bu.+N)>!ZKJV }  &ռyV«Y'o ٥KOcvAw#W *9 pt͚5$o4˺x MƌCΔ9AS#qm1_:nܸq`ƍSG.[Ԟͅ;&.c7[j) UYzJ ݮ̛$Lz|t+ꦿQE} +ÿIʺq7Uܬj5ӧ7kL=P  >ZhAjQ-.'NTkx6LJ?ӧO//M1@"CC_p@^@4iݽ{/_.AVgexΝlWg?Hrgȵwys8ޠm۶%q֭xb)SBƍ+WgF\?(mv'O(t_*,ӐB,3M-E&xNbZTT\"RJ8\X ^6jbFR,J;ۣIS$ꠅyZwvxشq>H ,׼ܶ9B>0 s&qԣi3~,{M?f!   `Fx?y#YK=Z\z '>|ԩSRF/fz@)<2b&Zg&>yVZ%e^|8Xw+:{Ծ}{i.d);wn5[x MZ8(ݡpmlo47!CʔFK( A>-%p}ZȨlRJ_(^Ca](6i!Uj2eP導AmPz^T[ډ (@@(,V6ڵx 'j.C)ҟ[2rBpW@@&#[@,Ѹ^weM#?vx<HJ 7ҩS<$@N^Bce>RҽU,(5q:eݎ]8ݾY`.z=H9@Y~"$O&σ.HX 2iVL رcS1?PfM驨$MN,ZD|Ch¯mڨH1Ѹao+Y `f=:p=9Ύ[ǏSϟy {6<<\?͘w>~]%oҧOO{^ . N  &&3A@OIgwq.%V2#4Vss;F mJSǺk/jCCH4QWz;HdW-nɑ a_B`D%`ф3XWxQEH akɐ]7Ѳ17TMU,&Y͛nR=?~ѳck  @/0#nfpV[{ƩljCL$*gӶQTTA?Obɧv W dNk&LP%YC5\ySn|a pv[<%yM}㚢ڟ&*:EվSJ>9g\2_t%)p[Olʉ'j_l˙*T~ۥp={Dg  I,n۶`Ze-gGT/I,*-Ji]U8gR ˇԓѨKvqso3kC+%|`턟Ʃk7w,3cF:4wqcw*bL.?[HZfS,wݿ11wM8pb :s ݻwO*rUںu+ Va+Wz k= '}04^޵gVv~Ӥ)7b*%ThQņ.6e@;,ď Qҥ1NA͚)2ڃpp3#+0庳|S]$guph!KRk*%nۦ%?E@@@@@5uO M֯_OSDɂqFzܴI?Oz2sA hXV>[l:M8+ٻ"Ǘ}tEd8|9Οߕ!t@y9ǁng}k>u:jڍ]Gc:vo@۵#+W*qCI*6?KG=6Mmx- NGf  "P_#ԩS7w j/ݼ[bDT_4f]C3V#Cd>.Si҄e˳gϤݽ9nT?7qhUSybsSJW_UC޿O7 w#Z}8rN\H7Hӯ\"0C*[ K$*q;ݻw*1Gvg_ϊeN 7nÐ`zZMK%EjH\L!s0x%C1uI|`;_'8tb.o~~-=~$Hgs{vk~φKN/00:t@ݻwl@@eAH@/_n#f"LNg?x-)w|6<{Jo~~L/@W QoT|ǁ!k:<ߗnޤ7]lxꕴ?ax)u*)ۗ?g/_J8bXOfxMz1g_>,-1 /^ !kڢc*|7{L Hrr\p̓޸I؜)J(fJZ2S;óHYio5ΛA@U\;{i&@@@@L kJ  BZD,y f @@*\`50ZZd1.7@f> k y    %aw@׻ނ(C^e8b ȫD     U醳    `|`!q k%    @/pqB+ ȫ1ppKhz߸q#}7fW֭[iر4|pڲe q 5?     8 @ѣ˗wQ֭)zee'N H>ۗŋgцwRzСC\+\*Uy<n    qqS @<@pp0͚5Ks߿O .\/mk׮m7+Z͛7/͙3֯_Oڵ/^H7oެP `\wn`u.]Jo޼Pϟ ΝKt-f̘AN,Yݻe˖TzuF 88h =    U醳 nHk%={Lu-\JjժP!ȋWOVVs_-%j~)yXXtl+ ^A^f8  ;vЀw]`VCn5m:!5G͜I+vl>X53yOߴeK) ?5kJ4t磐d ]N nZѢSe&MD7憿; v^y38zXYܥ姆+R/=~$1Ap0 ^DQ|Fɒ? ܵ%KX@gwxd|-+@@@H*q̙3֦"A%X|ϰ&xb@xϟ?.]мy촴}yݴo n׎i6e ^~?L,_FpV?y,,SJ9;_ocΡ1sЫ9bP״?D&޽)CTt5Tk҈gM6Cyinhڔ8]e߉ٴy~77Em|Xd=g:|Cg@6?[6wu;n1cJ)ڵ7[֨I+WƟsGիW^qw\>&Ҋ}a9;MódB@@QJ/i*Qn $.\Dc#`u <g&}<݋фrUv`9ٵKd}R51ٳ"0|K=pVe[Id!jJ f06y`?Uԑ .mQJdsdR["m];Xm?ی10=pɓv._S֭ c  Ȕ)%vxQW^iSwF.$Q:j2eH+ kxnz{ Af rjѣ4i /ˮ+jwe>-o@g4/jk !mm`FԸܯӳ'qa5ba19Y L&'F7̥TRrUعtH);y}7Qy+o^ٱ:!hyCpGߊZKN:ZuT_y*]/_7nLk֬DtQ  2xex ̘1ErY30q9Ȁ)SD& %ETt=ʥje3,#Ւ>PAb4eߙo_ wb>gƏl[QoŃlyQϼgD-~Oe˖(VlR3&MJÆ LxQFI3/O0΋Ć\A@@@&L  hʂ3{Nk8nTH+M8V+uvXZKD ?^ U똰jR 7`-StfʹGk~^՛.3׬?{[ Baat}̘1{nxI&QUwLJϟOS]5~~~ O "E k͈maoY.Qk 5c'KZ LPMEN\\0yKuRYkECp@ H\z@xqs6&@/g.]RLiكI F f6gKf^jIZai Sg_]3WhnƔK4iIY8E.k~~ 4 q}Kk-?ZZΟugE}U;΁Qҟ[ T1iȑ@&3 !pBl.t%Y-vlnoN\2AYwjz9͛mh;߰A>qǻ@-̟38dkn=xP39{H+(FMD-,… ){*̘1iܹ4hРs8O#(p]DGJ ۏv 1 p QByg[xóŦZ ;C\"DeAU=2}Em\-˒Z괥k)d3@@:YQ«gϞ%J e <_}@ܗ;w@@aǏWxD;cs`:fO? ["গ9/b^rP6W ONOY ?9cFa ;@@Y='nݚbĈŋboLcx:_Ow.2t1d߹T;.߾ҭtS_>6\w pSM/^5.Цea獯}ˆ' ZˣuZx%Sp@@qYTN@IDATRfͤr3^;=|  ک l^mW9Т}gzn zϻ?ȍ ojo=lY@B5x2@@wc߆~/.zM;%z[GߙyXzآƞ[Nzylj>>>SMĉ(z\S;'OnS$I ŎCzX٤κS% $eҤfũtԯnz}?M2}~ˏiɇ=M-;4ɴ?mڴq" w3p@lhniө駛ʜ: Խ!eJ*6KrϠjIo`FfȨ<0Cz]lșά M,Y4[&$_ׯo׺6jx?~ot5?|Fϐ7ٳ.gE7ռTǸbQeG9UZSMŋGm#["O^MKpljU5숒իQZ6Zm2ƭjڌčkb/.3Rl<CjJ.](M4j    ^J^/x  `@q|R*!&p5W׭KņcZʀm(^l}꿚9jGvB~1b6O՛62>Ș֯$l}V9Hگ?$0G&,-Ibvm:#\1 }@@@@@.m~5 @@8&OL1b̠t)R@4p]jfJΌgf鳧(bnKKbp@H7kVܶ&57QꋚF%KQ/-0M*;\i]5JԒ_ )S5|ISjTR1 X|; 8/%E%AiI )iIiQFJY:e]؅-ӷaٝx9̼ws]K596x1@8k,Z8_5}jXJOUvH5*}(Re[WU3KG+F,ZgvH*VtCu?4ء6ZV޷/k@Yj4s5VυCRՒ%Ocq\iH[A '9jyÒ%GjڃMxm O&о}{oTGxp*?8:RUI0!2fiqEEKӊ͚M-l)VG5˔Q<=ED'0 Npu'U4 .5ʐſqtjRaϧрv_8݇ 鷉G.9dAE pQlq05kP2ϵN:.^zuz)9rbv"ڂR:Fǜ~Jt#:u钽ǑO*KD׏7oPf?^|!pU˗3)W,{<ńoRDDdϙRf5c?~"sT)Sss%&,y^N&Fw f(l3?ӈO/2;w֬B,bt9ϵʖ#QPHHlsE4+Jh(yy7;~q 00ώk=ϱ^<6f_z%99sP1کJ+L2^o>ڴimٲoN]zUzH6-%P@@׌yA@ ,M68eC!μtR9 &D$_GH˕,F8;*7/}3u*E ;߅CQE|K[O`$s ZeR Ns)EqݻK/\qc~֍VBLz.MSfrszeִcd1-\##8sϩKψ#bZjŵ?O$ltR{v-*w,.@l}wΝ?KǏc.˗-ZPf͐ŏvѺGcq>Gǵӧhx <mlSSʕ}TmU3/hyQ7ޣR6e OʖK0|* g& XD>s.޼Ax&bnFq!,#%'N,Er5#_?qMeq,H{c=mW@ԩS'ѣöp4rH)jwys"s?*]ڍ ALJI'fX'аaCqtalƌt1府ϴ7K|vF -|!U Ŗ"PX"WG'/M,D#^۞ݴ!:|I`i3 <r"WqjV!oT9-3W'Dq=l<畄]Rfȅsc kt- ?ISi(_l3sf#m̍6cG)f;J^Iyl俑^ 12?NKc{c#om~1?.z+'w}![xvu0kqi.w +: <@ (ݢEҒ%KhƍԡCգ[@<"x={= ׀@#w^zbњ5kzta- [ldɒ)[luYoN:ݻwq3gP޼yi߾}RJ>YNʞ=; < DjՊn; M=@@@@kЉY .P3jQvho߾]_#P˅߸qC>L3gΔs.,{q^Ç[}&׃'D^cp'kBׯSpp =*TڴiC5kִ?o(Q"k·N$Iׯ/^jUx  C'n5c`%._le jPR{yQSʁK)C 8us< J:p@@@@<k q0J]Gw5 8.UtÇm4i[kx6.@^<@@@@@ ``"@X ^xpX#lݹsF"O:uwdWcڂ  +@@@@@ NyD 'w(z{{kjO&M ղg=~ddt?j9ڗ;D^MLJ EVuP+{^~M]tC ݳf͢/O>}gϞIc->&k?@@@@>+{p@ ʕ\FpQp:f͚ѦMŋS˖-3lƌcAAA9'Ͻ{!܂x8Dz"y9o@PB2eJʔ)pݸqBBBիWL| yҥKS x0p@@ǎ>} 4El1UD4Y2P߽K.e7ӫׯm_&e׏mK62ud0ۯ@o޴|"aѴz Ӻ˖]>lNϛ6ӶӝVDp߲V-][aaw$~~""'Iʔ6ȕ*+FKv[q?2*U ŏGҥsK+>/px oN`m,  x忇q@Iq'ٳg+Kz`РA4ydr-35o_ "zR^ v4zBbqah0*Y %J0bY(D3gH(/2{Psyyn:G-~Ϥ"bƑ)JFvJjpfu9ꇣ9'|DۛExxq4~J߶iCҤ+0_w殮6Ҟ)"2Ҫ,׫X:6lH ZǬD"j#9?0(^ .|!'+??}R/duƯߔ+pȎt bϞ=K7.~LLxOW'&~.>zH:̩Ҧ5+j>?b{S͟= ìa7 ݃hK@iQ9x9SF4g@G7 qoiu(aRϚӝQާBh3;ڸ;: "VGq6j ],\a=XlYiHbH%.Y,Z ^ݳEK2kd{vS_{jJ~^\u$!ӀvMIelk~"߮]E^k\oժ!RɭUQ^0Bu^١%6+)60 `ѱjժovP#՜ ε[c]7t9F ǏB}uVkb 偈*.C.|yf)q4l\]}LBzyd'ZllX\qTv9BEZ4YWoX6 q?&tF]np}9bnV/g[N@1ҮٳGm"lylۉ'FYELj}    `4x6#@=j[А9sޥ~y vm sQ]+'GMqfArN]%q0S1u~v'[\S8z6f*bvo`_NgRL.UX_xC^BPxCmQ@@@@yxg nL`m6=1# &Or8ߪX9xjmbn6pq^W#NK۾p\g 1Â^^6>v<}ֿ##SWOb{*W~0Ŭ>iY8 x.q4Y Z~z*W\tp;A@@@ u`7jbVر67-q8.Ppt_#ˑ9Hr0n2n"Ww]1iS86pL:z*p%U[N{OLϜQ~F/\*z0-%Y~L1.f(|qʕzF<6mjxEC'    `0x 6!0@@Ç5נr~y']ASvfg\D~KTl1#rp^~~diz_Ύ reek\ް˨bߟ'O:˘цNS)]kk>"Rs+F/R(iΝ;i    .E &#pWDYXBs'/[f,pȥe-uZGɓ.R;'r{:TӴΰysUF -/{?C݋t F,)oV9pbQ f6~*M8筊@@@LN'(K` <,H{Dj"7Qrm:|V%䥋 ㍥ndbGpNdSsȾ e8r&Z^F+ ׯj_@1ju.Un,s^{P@#[|~|@<^O} uLEb惇trPx,Ǔg|WmBp { ,*sfF^l<{Zu=\;E*Կqt\Y~vZT/ssԿX"K$I"f̘|}}LJ)B_|-]U#(  I zlWX DM*Okhib s~<>ֽ'w℮.v!j]jY/.ߴ]w}7ooEv84G9~̡6Vfqw߾}6C}'pӧ[fM0a߿_܍&<{S?'^sF)៖UmNj7| 9q={('/]b@/5HqLl, xuޝrASNu*Wmذ>cP>}ڞQ@LKi(MJwP/DAF"5=zh&Ǟ Cu0PmaUqi#yOk[n=ۖ)qO:X7n3=5&8 [Rs{mLZړ!M8cڴ$5}yY;ʱ/J=}T)A1&! p/=KL(A'=c&݅YK7ejvǘ {v[T9x9&EJM/pk/2iQ ̥0Q066*T!P@3,XLΝf͚b/͝ǀ nI[N+p@rM/_>g*Ҧdl'%>cAoߙYBER7t|"1qŢi:\%VGڲ˯$"u@㪦*ŋ+ҏ4yy'{$p޽!Mo߾&L @"/yA  "ի؃k.|cZ&OaUD ت'PJBUs0%λF Fׯ_<  `JxM9m0@@-ZRXM"AiIXToR21Z,f}}LijK,Y\aDr$Vi)JyuH!ϵ*_j6Rp!Śϖ>],ݚ4=-:5jDT̃5Q@@ڵk7<ӻDFFR6 RJQ ITMuj֛u1mҫEKa^-[R dÀv_hfK4˹!;UEC:W%;}]/s ^0 z4o ZjTA!0zh{iR_%xMO? <֬YC߷k;vH$FIV"$$Įv Y z|[;'-Vk6JDur6t]ltUӦؐ9}z!d,{ܨ RjKy]zjp-jR} }ʕIt,t3*N|_۶\tw?w`C\ij7>Z+GK,9x8ӧ C۷Aϟ?'^%XD=W_ј1c 2_|z,.]j4Be$j֬)a@, @൤  "OÆ 5c]ǎ/f5Pf|4+WZ]5E+V{"EQΝiӦMԧOJ'cE Л7o&<<>Î9BEg(۸q#u-^xAą[@<^Ϟx `5#&1FBG>m3СvBNRmyz{zlxjQX5¡CPjtHg@&OQ_t醻ZY$;L9ϵ _1{b9JtnFw;ھҟ?. J{ͣY ڂ)͛7γǏk׮]sΕL,>ih9ײ9 /[f$.rph|Θy2 Ѿ?RR],-'~mȕ.XV84n.)rs"'"Q=_8y~:ݹsǐٳGq8.2bSݲe˾B ұѸ3gΔsn#{:u>Nx  zs8rm۶QJR˖v0|,rm=[9ruw\j)+d !]o9ď}"#Z]-,!.tlծ4k_xq:l9CƬT\~\2‰,Fv.)~dRޒPQf+,n_fpNpvYm/7rK wN-Xv,2 ܂0gĹsmƌB,XV)a„ѧիc$חZ*i<P_+AA&M(N Tlf E?ĩұ]"lp4Tv&*̥l9:Mw97YbLMx(c䇳N1Eː&= U#Z4f"@$"ڱ]P>9bL*+#E$g t)ۻ"Œ oOT:mlqWWtkڌo@k_v?OgbrҮS>̑~({/ <<'L$ܴRʕ%J"P *@a<]rŰ-hլ5_"`7 휺lnAE ւ@@=zTvR+gH-Ēq{З; f)9/Q"˴'Es7-Xc4vZ:_4ԻUK!59}--sN}>ZӌU+i-0(Ȳsj&իSM9ň΍ >m9tH};iȓwۊ؛#sf,"vTFK6ͅ KMWK!B'c7(84Esy[e vƚ_,bG(z)v=Ȯeh jԯ\YU'y" '-l\ Faaa4n8*hÇNgwC{٪ FM8ppkҥ M2~ =%}:5j$-Ur"{V\_5i*E޾m,EE|isiRU)@d)sb߼OôvB+6bjܻMًEQurU  oߊ|Ɉ%H۝ oVbEz.~="_xd!_#̬"" TRd8GzJ6CqD^Ǚ/^%-l6l͙3'AϞ=яNHH8ذV^-le^c08bI&IWO{Œe^F<{≈Tb9U.Zn\& !?-_ܪ ǎ@\bŤ[ΫۤI+ӎ޽[:^z$3^a@5TP@VT>SU6,kӦd ׯǬ[nQ۶mc7yF7c={69r$xTTuܙ^~M+WŋG&݇     F "F 6(O^z.]:z;cǎl{uR=hƌ԰aCb *D7oޔ_͕+͟?8uִl2Z*q?2eR=\xRNMs} x6=$IǏ;wгgϤ/y!s8'_pllp@@ܗD^[x2ĉG_>-5jP͆iӦIyx @6lx0ooo۷/1&M.]J۸qh+VH3g|'7$x,;p&o>jUT={JWk֬yˉv&L2eX;c   @"L2\xݺuYfǫ:}R:Np58s*nРA4p@ PΜ9)s̶8A 6gΜCқ7o| 9ʕ+&{쑖Uq^ؾXmSm;   nO"O1pP4h+-[J)0"^x={vϑX9zi Ag3 L8Qw9WT>}&m׮?6mD)=Exnj{G!}5ח6 7oӪ˖-q x|PGkyf͚qo"fjOp,uNZPK;HB1B`E `n.Zɭ:# z>A9z7wvtxH4iVhQ{ϟSlׯ^?*qb}Ǘ6-3{-98;s.kyv׬nݦDI A~:G·"y'?~λk{JxV͒*U*)\ҥ} j :u;&9R\9^n~zz;J*EiӾs<?|𘇣s.(4z0? <}Fh!~ܓYɭO&-^2ӛt$Rz-7TCc6cǟ@o6^˛9o߾ D&MCX]z59D AB9x2S B4l0`vY& ׮]>uFRA$H9B={$N    {HJ #0aB⍞GWdɒɓiw@FF&S޽ )۵kWZ j۶-5k,]ZN:W_ѝ;whҥԱc19s<#Ec- GU xxprTJiunl{Juז_|cE׬c,\eX^s{cOŏk=TXiʕ4~x:wS_Z%h "%>dM@f|2}6J@IDAT3(eʔ9oQ#?~,==>fr-Vk~ N:Q=d$4iRDs`5D^L p6Ys 1U     D7     #xs@@@%WY @@@@@` lB` *D^# lP6YS"Ho߾3gΐ?]x<6U*ʗ=;ʙ9۳ g!2|P)(^<\?t  `B,z~~&&uxsQIԩS4|Zf ٬'eH-kբ΍S71<,~۽6<@Ϟ;16I(ϑ/NUJ O?Fg\a8QBJ~lTH*'[ Q/_{w%q7"/Ȝz'1f"׃&! 7A\'p5ݻ7vwv}hM'ذ+Jnp):v,"n` Z._. }ZPn?ΚEo*ZˌeЄ=M/E6U+͛Z_(wnݪ %H_޹C֯?iu(aB*S}V*]Vxw;*E?)y^zE}|(W,T`!iB!{y4B_wD.e*Ӿ?"LBWPdϻn*[;K?Hq`24BpBѢfxJ:b.E%~^E'PXDSvv}'"`@T\H,y8AG}O,p:Z E ~hSt$O۶`ѳ_۶6¯ WmFS"j=,iRvЮ])yBĊ~LigCimn^w_DcH(.`*Oʖu4-ϩqG~r|L)~^2ƚ=~wÇk!mڴT`A*Q%Ps7[yfC6A~iͯ@ԩS'ѣcLkI PZҥ ͛7~9o`)mM4#ҍ[2sU*V,_# #h)9qŏ]?̥3dQñj 쿒~Uh1"WqY,%Ny)1na6C֭vh&vNL&OJf)vZ DGΝu$Ә-Zlgls$%K(BԵ_dj'4GOE/dY'f/gM +1ƈKJ^K-[!CPfc;_Y1 `sc 0S&{2j9kX^OoɆM%]ݻTWbcgzfJ<ຽ{RԢ]\B+w=XJ7]w٭.|E*޺q?OvXe?9/sɓa=XE *;`q}/?oD[4Cs5Ŧ'N" q#m@s#FęV?8    =p[gΜ~n5d0<8t㯿ikO /rXu8Ri)bmIyH| kþ}4T6z.TLY6Cr$Jsںz,,#vB/~w"8ra9LyDwLEJy#DbsLˆ1}Ç s~ǴA@@܋^Ox n"r]0R@8k;Gu7v;{*MYfF6n~8Sq"Vgކ7㜻j9=1\_WgхNVR'r6lk>'P{[4?+,> ti8˗]GmEիW;="Of4A4p^g [عs'8p@3PϢ TZd"={ 5Ӑ̃fϢt^n¶q537@̻WNQQ8/;:EAO\/?1>&.nߔ(1c~R4*a}L'ZcSw8Z EY4#f%F)V~Rx7Wgak]Eǵ;w]_M+4,Yw.94Gn:ߡ6V^&9LNG6֘E -sS(]8zLc 3МCW)ˍRÚ?~D#oS8םjF    (C}&;oR=Vn3r.ղ,ߺEbkK*K7mj(yf͖+]Qiuqp467o{vQ\RD{׮ֿOygn|Ǝ^8XR(    ZP !j{7& "ʇ.: 5yZpCvlnKMX>{TOq1s&xjIkzKbԚOҎԋ W ^Yek͚5j7%8kܹe :8y3KoFsEW4ڀG5Γ+>֪p4w.q? @<ǎqZ#>i!/UXsI%:rrE( M$p   j6a `*W\@v3}sy=}ǜ["W1ܹn4NMu*^u3*ga?X1Zp&]:qbB mgP^ Sxn!MANKIy5 ok52g'=(D׾~{c|]Y9Ԯvo0H=5Z`d @@@@}xg@LDU[Y/޼яo仚uت(vŮطt_މ[R~PTQhLK|~V\Z]+o)  PJ@l F@<c>Gqfˠ;JinCZ-!< .jrV `oojZRE駟Rʔw@@@<^ %"Z57KK_pagouE굨YK~qՏ.JZh5]|^]ԦN]%Q/?h:kWS[t=ީQ#UMWWu W:i3WڶdTc>[bB&MT;RBqT|#FP;   +D]v"k 5`MmVxR~@q?u.U*j<"GhU"%8*~՝ɨHyNJj>[4j-"Q'د6vU)^UX;d@vJtzJ.Q@(    ZP "P~}2ozt֤t eHiElp. n%%KTQ?u6SgMrZ;cw'ǫfһ##F{Rk;h%N|b~m*fZ-;Hc%K7qьS3C*y9W'xuQ] (+.L:4~PP&ٳ5R&ONcn(,nȥvh)SV2IǛ-Y;[7gٮsTM\qon( ~pNCSD~[?eOuƎU,?4 S|9K"%m2x\)9:w`#]Z[hn͸qq 2 )~c   Eg7G bb%3VԦQ_}&SYONj֌/ޟ\IrI@Z)T.]JesjdIкSDmrZ;ed,8xYԻU+YώsQHb@@@@@Yx@܈oXXSESgկ?qNJ /_1f7Z4lխPAQ9Y)Sttg,TkTkw:Q4*`G2KWEנ/1cۅ(\Y_?d(Nfù.ZL샣%xcAN-gAOK{ĩ-w|(?Y9jRz 8JԊ@{!*5!@@@ N^oE*I 'XP䨨(j%Dk*]t#t:t~l;Q/_Rhնmqnw7 bTB5Ry4*0sQmF2~%d,*)͏"]ΝKo޼qzj|L]>HdBvN6~=#&dNb }x}옽M$1Us~XNwVo5X_}C;v"Nu[ !~4 v ֭u{٫Wc.X.W^0SMx`5YXՊ_}'OЙ+WaP0{#) +/k.yLI|1au/9c<ݍ4Y!Y;}:u=zЛ^g(J@icakȑҟĒ%IJ Q42RQ6:j% 9#ŲS'KyiAlowSG!o9bGؕĆhwg1*-PCuqE>n"ה>} ,&O˗kB&ؽYsݡ"q~ %qz"A-Sh# `!G.P~vnPi&גpqI|C4CkmRd}x@uZhC61 Fxeӏ=*ra*4o(_?Њ-[ќ, ˕;7j, ^9,"wkns7k^&k֩etfVzݽKg.Sŋ AY^S$Fy!L8W : @@#W; @@j [nbMqkb&ժMGC!-"x sU.V\vr0A˜Uyl.hrbs8l٩|"Ҳ]7Zdσ۷(8$TrO+6L2f$k"E fI+5oD?9N̸fxfE^< qC+$n( AVZϟ?X|%zD ı4)RR٨XdqfqT*e8y: UD2Lln9dGbnϓ ?Y'|0xMf)LGysA"Qk5k֔={Fa/KnؤІ7MCD,s9 @@@@@@%"//(    JD?      `v@B @*2 *Aų@@@@@t W@@ܐ^7T     `y1O@@Lg=n?p@@T%WU@@@@@&7nF   `^\p@@@@@4%WS @@܆^J8     `vy>@@'W{@@@@@lk NX! = @Փ>sk     B"L4 @u Z E>s O@@@@@ܐD^7T    Lt     jȫU   A{#psy|8I @@@@@&Wk@@O@4(p@@@@D^M @U.@U,sk      M"o4 %c0@@'yvh       #@@@@xuAA@@@@@@Yy@@@, e`'A"op@@ܐ^7T      zs$3^1n

ObY5evd*=~V5_~y(s6$J#>o&ײ|Ӌ?Q@@@8) (zn8Nӧ7B ? x:Mn~2 ou܂7iy+>c;u!!x -QO&דg?>%LRHw׮]#|2=}S))S?RibP!hG a7iRNas"""hdɒ9֓0/^HǓq8; D,Nz{{SJ@5mre~,5;5˭;-{HI$Y8ށڗ/_Ju5.ac<01lV8 >yNjZΝ;?ʕ+͛S8OvР%w |  5$#U, ! D…H$"XhNKɄoKYeqWkvfdV~K؏J~y;g,g b/'<9_ p6_D^=  `^+Pp@ॠ}͝;7ZذV@ӐWd1qu4nbIԴ#żoiJ4KW*;e5S繜|k{rEPƍyE 'ۻ>EʗJ(Htzg"4z `>A5bB(8 1 8p5kFߏyʮ!bi_i͎z8ʞ)]Rj`!j]vؤ O4W06:FAAgZuK3<}o…ATX1ە ~֮1у'mZ(ҔۻG=yjيmCIՋi'.\N~^JI/moQ}Ӻ5>K9tnIu"%.+U-YZԬEf' Q#=|H/E8Gy?+͛c}!?g{   `v^ ;4,~hEĤF={v1W^>y) ̜Iծ4ipj)[01u䥡%44Tʀ9Ymҿ¦+V:t;[=A^E4^kwP䥋N3VC% px2Gsg[m9 ŷkNm(;"Q^*)*m*҆T_DZ$BH)Iْ'd_B!;,sΙ3sy<,{=yyƼc=R=[LM|4gesIQ{dE$h@wߕ GJE2۴h֠A,ٶ"M[>CҟJ}iY<^R%3j(iR+X]f"=?=o)v~%̍BYS5ĹzwNӠIh3YݥW^I -@7/C 0awynbj#Ț5,ƛG;T _ &8ޠx?1C'7]\/Z(:ysn)SirA}H;-4ϽSrm[ƍeGO ?gƇp35KI Is'zhl0ht3ΐ榈ݹ{<ƛȫXAhLkgШV1ʉ|~x`קfΛ'M!MeJ&߱uqie _63^WoּL+޼-on9KqrXg^jpn4pt:K;\/m. Lp[u+ijWr<٣G]-[q|dF%~weWd֭am;vȩ_TpW s~}]foм̷ީo߄Q,-$:EӜEN= >"M$u?_Fx'9uާ Fҟut\.5sn$&އ~;b|?^tzO,D&2yGj`Igt=Խi~|`nzitvz~֔5ȫ7;8+Aޝ$kdWYTcǎ#! @Ϟ@ |cez^Ohg}Df/i RG|i1.3xծ7o _Cv=n7YdnYYz`t+~QWn'^9^|7svvfi”tn-\ K Su=ޢ &>ik {>is3t-'Ij֬hP  wjE O}^0,&=ǣ[o CK=fJkf{+OosB'y޽{dB@r) 9Əc/5W_{[Ikٯ|]#h)S(2QRAC?܏Amu{_mnK{{dV>Դknk0ŷRWQ=:rOQ:c~_gN#I֤mnLQ,Sxt~Ҡ?ٍӧe*{~65(97'Z 9N:dGoj  כ@ ?i2T a,qq`7ڼ`7q\|8kHwjϋfM)E޾HV5mv_ϝVQl⫹?zC: **G}'ⵝ UoXFOvk۶mXݸ!n;Qg4-zh\߮#Y~c/Mm]_vd;bd{N3ņ-w# ~d/,2bZmn¸-ZF1  M MGґmAH{3vknK:c`?C?jSλmk?~a'ѯ2oU΋{9IymcLyAB@gMM EŊIK9+-Vv-\8g3~] j_E/X'%ŋxx@~ŻJ-/KKs̄Rŋ;?[a{`3@\ %!@&臒2eޕHVP!fOU9:uZbe{ϺbVxӬ)~?$*%zHkT fߵ#5+UN?NY%fOKUzRWz5j]ԫQ2*Pp) }QGyLE@(xr@ ||Z^g ˗.-tTZ~VגyذN{uVGWN59HYSפ?$iNj6˷7lY]}geUVQl J/Rn؅SD|NpۻR  s>:o9@ n[7n{*i(B }׫'9Sw5>JOHp B)U*wf˖A& pV';S<)BT&qEZSw^N9յsR+))tksd@rWN@p_!ԩ=yOo:cUvmcvu_ec\-3sx-Z7D;j@Lke{mF8x8l:+<@s"ڝMלw;yTk=x?D JsOkR-"Wwhm ~]JAL5 ]{m~ioӏ;.zoY3fxl#9Yuee]Fnmj"m[M7]kG%t~^z/#C|Do&o&s(  @xSpL{ǗH:w.(vs=|eͣ=.8:TrUWyUUѵkvD_E󈺗.({G<+.->qp)RHPB;@Uxs馳 TCr Dynŗ9O>JUGnrj1awHjidu;騰qX:_F>`Fq_ݱc]Im{ҠVpS׉/|slq|ˣ=,珛7H&'LzM`wA&uR`c HQ&^ Oi=/DTسWdt5z@xs K`ĈR>ckkf#eg uZH_#ՑQn'nym)=hҏF_"f#6!ёn6׍|+CtbԆ7T @PyJ$'~fu^Z({ %:ھ|x2Y{ GS-2 '=h>Wٞt>LO߽R9zuёٚGo?kn=0տM N@\/gI^] bŊ2dW4sL9Ik.Wʳ yxswVթ͛ˤ!xg)c>P)}pFٴm+ubW 3۷O6olAI~YR0_B*]L|IL)ݻwlٲE GX~ʥɤ/g;.:%p(,\P"&fT}/ OBmқ#ysf<2_uC·W_{]o3)[Dc›}(_|Q~]*jSi_": ?]?=OϞ-\fΛ'k6luXY@:n-0R+aW$ޓbNb{]y*WYݡۮkw^w~gx٩SUݻw^.Oe)@_zSx,vW;m4ion$}lw򐡁!Rf-X 6m;m"VA j~^\:W.]P_f.lF1#"2Sj[7h _|Tӏ;hyRr夎 ;-uk`_ ?Su..R?,g̈[^d=PCCs1aL5KvA,wRXY1d/VʶEoV0֍Xf<n=~xC&y &zɏ ^ũ<" ^x\lRj3gySG4)۸Qyyzr#):gwY<7^Di-Z3Qߺ5j$r~xL47:t$EM1n^bE:'e^1 p൫߰e =Z^Yo惾39M`}c~*_E˖˖۬F+-+Gשc=MwsyeEבGT&8a")DU^gV'WW[)A^_o ^(^@IDAT <*)z)8plڴ)hk`,I`3W2`fwks+\M=^kͣύ#oGc4ݡUkk4U3kAg5qVqe tթZMoxoJ4i;$k_1ZW[+hNΫGU<,k֌^fw$k~@&%3fqgW A^/2!M \@f>}uf7xCz-aYL}tgcѧFÞ8&H-fnCqg}d#Z}?礓Wm_G S   J@@]zR   @q؍ @x"+   ;yq@r   E oZة@ f ;   @lV@  YM   @. țN6]Ep]   ADȏ J@@@A@ 2!;a4@@d|v xPL@@@&Mǁ Po.; @@@@r  ]ot   D o@N@   I o$!v    @dT@_L%   n uKr@2Ao&E  2]@xҰ@@@ y|vh _x@@@NJ ! Fs@@@ +@%@7woz  dAތ1#b37o&E?KCJ_"}BJ+0mܹ{ oDhQԦ/]Z.n{jբ 5O糿-7?gLɒRz 9Q#9Svժa잣6g,\TVY#;wbEHʕ5%~rH&@ yӈO )V ELذa\ve2y䤺hr9ǍrÅ"Ht>O>!Cy'Hm۲}<0+;{ͨޖbk&YЌ4ϳomy]syp^RxxzV=='L砶nںU~]ʺq3OK㎗oA֯Pްn6ƍ)3gʮ:v-Ok;/4k~oЛ\̟'Sg͒[H>dB 9g+ۿo>ɗ/dD`  5  M͏@ \RN;4_RwF+\hzM61v={ýzI]-&-ٻGnN}aX3uLx hnjޏ=*:ribkݤpW?9zDŽavCdoEl 6o.{̨vL1~"}|;Zκ٥A.~ϖiLNto7*lW|[|ȁ <ȓG&ЩS'nFE2dHɾhYmٲ,67SN~AOU,YZ5sWf+og )S&tБzϿ.tS>'M<2tGniܘw*ھU+y롇wSc7ZJ,nFW.\8bFO,W͵h*i%5piCšV]+~[v]kދ7tO+쇾~룏!#>Mr9fR|#}Le?t.aH>*&y糎^>wr zH#hjyO?Ȥϯ^yaT>PUJ[JGX6eLk5]LɣIh3⋣:Jw.̍r 2gşHc"0<oȑ#o?3r./9sήwJöԞa?wjpW{tȄ/Ho֮6ju,x͢s؆%3)wM+'=`H_rIw{9o2s$]DY+jE:r43r{ t7m̗'NƗ]*_cPR;-_&ǛrL~5ks:+δ jcR쳤5v#L+yxa͌-IĤ#y"! VFn|yguA9Q  QDEtt:w7ޔuDJڷtՋTT)qR|^12o|ukFZ7L,{4[Ӿ(fe)Ҩ^Tx X53#۴1:uO>):tzsC/L O̜'(a7nTDD_wݭ[mf?F?^z=2ZL1V ,({$=/$V7i-cNnS1뮻N1jpWSLyD$S҅_1qM̵#/i{NTg~fmgџDgfJey23mK/ >1SKzg|io Y5HGmjdnt57֤fy 4 zz7NxŊKۓ'7VW^ $U}|O\ ?w%(~N֤?f:ag&W_sl2EJ:7u+3W?̉-TMנs7UC! +L'H\`?Qb-jV Ϛ.bk/"jN932IG^$qv~&,熺6_ tj07$RI:jNss8IG-#I7OF s:Ӥ'_;ȫ[?piݺL6?$@$@7Hg M6jRO?V}'tS]A ryE&V*¥KS+~5aNgGoFji#mNfq(yUӼ*>r^0^$ 57Ƃ3S܋Կ7?ȵiڦ7ޟ 0rv9ύcW}?LJڝ\CaNεH_!ϻ{riۦ߬t3ϙyI EoP@ @-Z#w˕+eժU/ut rq D+h9uXʱ^.m9ϽGcW=iߌm_ rPt3Oi 9},O NGSgr})f$}^p+FV;X{׬S֤s~8#:˔)M93jwziU5;@Q+X)U!@t`MrHԆ ̚;2s֎1HGjp֮3jb;wnGY2+_x%.p}:s ȗP+˧;-4sO~]RR.d'PjyZ_dvvߓjZHgFڦN^ H(7 3rg{p뗕+e\@cFGkaY atiVdNw:M5HF,7Z~:@q]-KG~cj`1{ҟ,Z_)} pǭ @4d؎@.R%K`s؄08O4)jjԨa +Z!:i?ٴϴwhٲV?nZ?;䯔Ϲf:\7czt;o/ț ^MwZ*78{a74y+_*.Tލw붺;=f!MWy|"Ϳ~ɺVm,=ԍ+_y9 _)9ڵk,6t7l*E*s*;>dF@@r A9W˚H"K/]^Rݟ? #nԪ%8"զr|^?~7JR,$OmoFg%[T֗|Lľkgy&Ծk{^β:ꨜz}Gzz{?S}^$@ &vrZ}ŋ+fy|TFT?~נOPS5:{*- UTr4hrNHpO?z9Wښj; mרQTyo3cv6k̳7o+|ӦM~.\@ǭv-iƺI/~:z~m[ossB5'TGjWohEN3s&k$+ߟ{=SRcǎQ7ڨQLb^AaD78@CM R{ĭč IG!KnT'JN86_[h!~MS#ZjK'Μ|ɉpSN9%c:@;^%pk۶mIA*TֵrQ:tp}^ 374Xt饗.,2U>ѣGRr-Iԃg>  @ w ]"H@?(X]mY>R7o~vgvy E=*bޢ5G:&:tr6 /̹)m/G)SƵ`iE:3)JxOQnaHܺ]kN!pWVu]Ts뭷2ѕf)sΑTn(K.$KV#\@o^]qlkzܹru׉:3dpBIu:8U@&EfrΫkOM￷ūύ]vue_7蜔~Kvzڵkg4|~i}wqӬ ܄ "Xsph,T_o]'O<(ӛaJLuk 3z>}lm}WWU6x79ѳzcbĉtNnw }& >C2j(9rӚ^*Z~# PNB `>yweZ=#N:WgzoLbvju иV׸qcXwm35\<Ʈ^;M4)vX(>:\Gi4r3 Cmڗ}IF4lذGS ԯaM@ڤI^CI?tjg̨Nw 7|L6-t72S  &a:[1e]+}[^yg媫/Zo߾h̘12d㏳Kl⩧4YbE g!hk)I(1bn'EvjP7tu.RY.9>Ð4Hp /FQ~GC950Fhk>s/ }DIth/Ȉ 5k}qyuQoVk&[7;/^lMKS0[[b<\P.}A@^'JA hk>N:U~myO|ngW #y^$ kV܋(S!8pEe+CGDi0I<|AX >fFM nڳ]>KJR*ZGq4;vt)M'xݗT8Hk E.ѧX65CNrmެ^sΙ3?r:Մ^3gδFT$ޠէ\Q}DnӬMW_}z?ߍ7pev]  oRrr}XjlܸQttΡR./kc44Vrt57O?!n 軑4PCrִeS<5IH#o>?vi%՟Hԛ;ڼysq|Ç/)uy1ˮ]hOo :CaH۷o,Л}.R5W5Z]f"?aVlmذp" ݻ- Zo?:{ҫW/N Fda#Ut\pjQmS-uѥ{GR':2:g rW۪timg2IaL~xK,+Қ%ׯ_ߺ9`Q["O? 4 닎՟0?|eʕnjZ ;F rN< MO)#< f'2ow\gjx'}^[ A 3C@ )/vC^z%k$ioJk*UiڴiqAɬ#ˋ-JIݺu@Zyݺuү_?5$ik9+} ܟ}YzSDk r ڝћ5Q'/k$@v9*urKZAN=lBZ u33 ԉo|h9Fa; @PLpE6pւstZnIn6)V+LW!ZŇ曘о^x*ha~t?PfϞ-:N:BWGuį.&e3>},\К@ȪNիg`oLѶϬ=]A*~x;ϬM7qCG% TAmB(sH^gqԨQGYlvYEزeKk$M7@ݹsg>z,X`nǕu~YɨsQjp9vzU ?Mz5[P!k> xY} ʮP5/o Fnɩ@@rK@.f ]؋]hSG5jժG5}e9<ʕGB@@@ xӡN q%K<0ר,NB@@@Ȍ@@@@@ `xvBh     TS)!     Bs@@@@@xJ@@@@ހ    8 T|     @@@@@@^RC@@@@&@7`'     N:"     0;!4@@@@p*@ש@@@@@  9     SN3ԩScV_k="H;L &/N0tP8СÁ>jJ:D<%矋w5K/Yך-ЦMZ:vܸq_`C=$5k֌ Sy %x !{o SN9%jޜ;ܼsp |3ψ40@,"kA>; |;vUgwF\|VN?@Ο?6m$%Jve[\9z4"w 蜀>l][sַ: Ipv֭[g}թEt_ܾNxϋ̶DC^n]ݻCݾWL@ lܸQnVmݺuv7`\"2 XoOMC4 [i4שΓ{I'Y?SkΝke9䓥@e?ӬmJʝjՒ38#:B͛!#tpD+3}+/#:?Z7<+}{3Zen_a{8Zқ:pwl8a' @!'&"?-**ZH tHfi3}ɲecə׹@ .KͶw^Ѡ]$+Ϙ1ú׶nkԨbȓn_'ea?nЩS'}*ܾ.Чג~{߻0&;@,@7'!C9$j:ՂG͓u]fRneef;/ V?4isavcΜ92~xy--ZX/_>fen_' N4IN+sW'\r @ 4oܵ9x/"g}fok.:=/]D.uW*԰aC]v¥zq-'x@#@W^Xm۶mQM}`۷[E9-I ]; &Hw^o_^>f@ yq셾M2Ūҋ:/^q|N޻0w\ S4np]a;{衇F}жxĨ*aClܸZLWրqƞϞKPA1LB @ yK`ԩs֭[ʚҾD* 7`N F!@7/@ TPAg}\lԬY yYׯоH;0k "{.r1#6m$={fRF:g7nɓG IrNXC+u{^h/5/nժB2 ZN^ ﹣ / \  :䓭W|A.͚5;h guyƌV8g&M$6g宻}j+&:[|yDW^{)u{^R}O/ÁoP6 Eo E. w=0V7>~JzaYFFeۺu}իW-[g{~Zyz7J@ G"E]0Ho޽l]wu9 4hP L~モ H׮]7K DoN{޼ʚx˪֮]+7o9 O%7 s, [L$ @Fԭ[Wڶm+'O޽{[̙3eŊs\R bmoѢ*U@Z~G_Rk+4j@~]z矷: u-&ODtjx@wn/Rǟu*~A-ZdY);3R d̘1pB멇N8!y8xC@4EZ|B ٿy?lP& @x#?dQh:QqAjժٛ} Æ -Y:Nܹ\q!Sf h^hT#GgyesjyNxT"ׅ%5W"h5r>w7`8D@T*     @Xd-MT    *@7UAG@@@@$@7MT    *@7UAG@@@@$@7MT    *@7UAG@@@@$@7MT    *@7UAG@@@@$@7MT    *@7UAG@@@@$@7MT    *@7UAG@@@@$@7MT    *@7UAG@@@@$@7MT    *@7UAG@@@@$@7MT    *@7UAG@2T`ҴiSWoڴi{gi׮݁|'O   ^M)@˵^+?k׮k׮W>#+O&Mm۶a  x#gIM   бcG0aՕ[oU}SOGjժ%s̑%J7   ^o})@NpG˺u$_|W_IeҰaCߤ`2c kJw   "hɢ  @:t#GZU۷Oٻw\VpWw 8n:Nu" zFK@@@=dȐ!Vfg^LΒ_ r!  kx] @@ tƍˢEtRJ?Jrl@@O)&@@ EW^y%[yDx  x6@@ &M~A%!  @zǝZ@@ ̜9S `hѢׯZ`-t  d 9t@R`ǎr[u *$ӧOzYU_f͚e  QFa3  z-K,6w}bk#Fy޽{Ν;w!  /x}a@@ ƍÇ[h֬㏗n~r-@@ oRHN@@<Xv}ѲaѩfϞ- 48P]aÆ믿Z&N(s΁|   0[_JG@B-pUWY]Ľޛ-ۊ)":UC v-b>6"  L)%"    0f*A@@@@ )%"    J@@@@@oJ     /x}a@@@@@}R"     ^_@@@@p_    "@f*A@@@@ )%"    J@@@@@oJ JU|IDAT    /x}a@@@@@}R"     ^_@@@@p_    "@f*A@@@@ )%"    J@@@@@oJ     /L9IENDB`latte/tools/countExample-1.png0000644000176200001440000033450313424210303016033 0ustar liggesusersPNG  IHDRx  iCCPkCGColorSpaceGenericRGB8U]hU>sg#$Sl4t? % V46nI6"dΘ83OEP|1Ŀ (>/ % (>P苦;3ie|{g蹪X-2s=+WQ+]L6O w[C{_F qb Uvz?Zb1@/zcs>~if,ӈUSjF 1_Mjbuݠpamhmçϙ>a\+5%QKFkm}ۖ?ޚD\!~6,-7SثŜvķ5Z;[rmS5{yDyH}r9|-ăFAJjI.[/]mK 7KRDrYQO-Q||6 (0 MXd(@h2_f<:”_δ*d>e\c?~,7?& ك^2Iq2"y@g|U\ @IDATxxT7@ @ziҫtRU*"M ~((+z)*M*wށn손d')sΙBțw.[E(     `@@@@@#@7     P8    =    8TCf#    xy      Ё     ^     C:th6     @     P8    =    8TCf#    xy     vl@7n̘1#[yE33ff#iuː!%]FҥKreo 5S;noƿi[T7L~R| 7&nl߯RJү_?  008E`ݲzj]v5Y:y9s4{t9ɔ)7?… bpͪfj%K/ w._{~]/qqqFB`LLMKZ-_\f_C8L"NȞ=1"͚ 4{?h۷OEnj[ĉrIS1**J"##}_D cv `iCOO7^\ryEhW_$>| /r ~^p!/`C;r䈜={Tֿ]xju:܅[ )gs\h     SO"*     )@70DžV!    >$     xs\h     SO"*     )@70DžV!    >$     xs\h     SO"*     )@70DžV!    >$     xs\h     SO"*     )@70DžV!    >$     xs\h     SO"*     )@70DžV!    >2A@@`2yd+WJ޼ybŊҽ{w)[~ײpB?RLiРtY2eۡO@*   ?(@w9sH6mL`eԨQ2`ի)ɓ'/uL7VZ%_} 6L;)\p    R48ah# &M&MnjdСb 馛$..N^|E1cF" .HڵMp7K,ҵkW`ŋ套^3ի4It     y @( \tI+ZT)QQQr&[dIٽ{G7nkĉ&{=y'\oV)P<Ӳh"9sw}l    f:ah# SN7J̙Eg]#""BufvuV]Sre9t萩?_%aaaz6{ᅴ:111p@@@@ ȣC@FaÆ^%"##J*ŋ].]j5CR2eʸa@@@ uڈ^@ Dcrjwuq5M0{lw…+W.QtI-HEBl ,m۶]w%=   8QG6#! O7GұcG7n\Ϙ1C*ÇO}ԪUKZj% ˗ѣGu& Cݺu]:{5+W4.]$f͚rA_~1}e޼yk@@@@)x2R1;łn=ߖ 2mJ.]Dڵ,[̥dxΝ+7˻?3ҫW/sϟYƌcf *   쀆D@rubŊ2x`Wp>Qti4hݰah~]kvy=7{QFyE@@@1x3T4-… :|Kxxk}e˖ݵk׺ ,h5Ń{WkC٬Y3sh͚5F@@@x1L4=oŽL_{M6p f[_d:pdɒ=tP#   xzxh  ru~ݺuxڱc\rN^]ĉ 79bin脧G@@@ 8@ ttfn ŋBhϛyvo6sLK,zU̹RJyMbN    xyx< w޽{ .iӦy8p@s<[l|zQFRresO>rY ꫯ̡֭[b@@@Gu0HfEСCɓ>3Q'L G?CN:*oe&h9l0\ZtmeԨQ&BZ|K+hP>2u5pܢE uu֕]MZڵkΥ.6fBg=jw ,\5QBtڵktR3ӷL24E    0f:lh.8[СCҳgOy7Lp;!{͛E=d͚U4_ه|âAƍǫ7o^h:ujs)40۬Y3Qh~8Qp7a['\^= &Db@@@x9l4*y_uq4] LsڋybweN7l0Q,YH:u1yOV\ikzDU4h`iZefq8K/,O@@@ @'mD.M[Μִ :S)Z9eOi_4֭[J* }M3M%5s"q;vY5RҥKL 7Gvȧ$O@._B:pw?3e Kk7gbj" q $r藿ȑ#jΜ9^8pk=s~8޶ѣIs۶mҴix׹h .ZELKN?<ɹ$!@>}%::ksf7+}|3g$iDGe@@@A׀% @Z i4Eiр?Ů{j"Ex}d̙͹Ԛ)͕+36Did>C~m[gTyvK?-8?:3R[7染]K=ӿv-ͤXZ鿟>l#@0  Ѥ/ ty1}Jc0s={$Q|YX1oo{РAfwz4jH&M-5k!VQڷohjٳX9'Np|E-]|!774ŀ"RH-,taW-_[@h*-u_۟OEDD:հ'\q@ PAc@jǏm>oɟ{jFtkNn,XPڴiw}*"   N%ڈ!+`ൃ `3e}xuXr]iqo}|~>g9!@@@24$?~3VFۺu*j*sB '<3Y^:xŋX'k2d,`aR|@j6mA@@@.HqZ~}ssOn5_ҥKyOiҤpBq2w\sF)3R?qF`w-T"-֕/M|#wr=r=LA@@@ hJ֭[~M:5ެ۸8y뭷;UVrj'N(u/8.0Ȼ++ٳMuv"E_˷#Gʧ}-[J4 ?l!  3f5@MlٲҨQ#g1Y]I}Ktt քeʔ)f3;wSNb 3glڴItkvEL෥VZkfGVg®~@@@ N@i}y OWRhзhѢclhxԨQ&ud2M Ѿ}{i׮?qn;Z   Oo<v@_~C\;vȡCPB#Fx='4yO 5 F8.C@@WRC@Z^   )zTC@ ]o.'OXYr͛W*V(ݻwe&mqˮ.]Yɺ>ٕ5k]V`/~Ϝ9S~kӦTTg=*   Z &0g@Çݎ̟?_F% ^z;Necǒz]C7%1bL>gVJק@@@ cC@,I&KZjұcGWlڴI/V_|Q*T 7i`R2vzR!AYf|rshѢ?Dy7yE@@p^MFBE@}}-Ue_reiҤ,YRv-}=vW._ք T& ;v6L7odgy@@@g Ț3ǍV#!!0uTٸqdΜ䵃v#""[nfwŊk.n{Qf͚^ @@@ u@ h bֹsg^~"kܹs(Pc=8w8^zk4;D7E   hޱg .\  6ڗHR9EvXvx sW^<9rx=k~'lQԙ3g$..N]@@@p^!=@R` iٳg< .\r0;u$hJ?9v<_.ǭ) ףv|[oȑ#e˖-Ƴxrw%&&&`h   67BHe|9;vq{3dС2|py衇❳wl̷fo=}8^݂)ٳgeݺu+Hnwx֭_j7~x{S"  8P&# `:3f(۷ӧKZUV&׮RѣGuf6jݺu,_^|=>{}d|@\ ^Kׯ_%.=zM΂Iwߕ?,k֬yE@@p^ EBE`ݦWW|%C+냶mVt"kڵ,[syyOo<\\nXA]k&+W,Y4n:uA ܹsv\H})   S3N@X **ջVpVs]DҥMS7l ,OIQ#e5cU;=:QnoU ]Oe˖Ҹqcsj֬Y8xc   )@70DžV!!/Ppa/} Veٯ/FFD^L1Kߚf!Npi!S@@@ 0o`x @4p/^Suo|i&So̙X֞_oץfO${[841W.v ONX'֢svٷoDFFڻ"  8H"$PP!Ww׭[Nq%9v9C@|\\Kk_rxcP떯{HX+V۷sO;v7TRwW@@@[TTDHKZzuYt,R.x+{˛>*n 5'qYfWҨV-Beuz;*{vV,ڋW^Ӱs ~k[Z'Ol=Z:5=n'OKA@@p9x7f޽{.\PMԒ-[6i֬.[ԭVM_wZc?2fhNW{Q+˴] Z3y݋{7o:հaC}q\74`W_CO=)@@@&@aFs@PE*V(G9sm5c &CMח VZSF<ҧY\ڹˤkzHJ.mLw.ӧO7sΕܻ瞳O   @R48ph2 *aaa2i$iժ_^4ZhY;k&;w6t+'lBHܹIe iyؚe/\lYYa-$A/ݹs>}Ztq:MPvm9qℴhBY)JXc5ܼyu/J S@@@) ^gFBF@g.YD:Xr57] zi^[4o?,Zm$KŒ%eɸJ;yy9"s m{O<+frȑO]v!CEf͚enk&Dڌ   3x` @ @t1cѣeƍ iz >|Xn6Yre/]V~%`9dt^td\36Q@;1_ѯ۷ˆK=}JT"wl;o<կ_?9y1Lx   h>.(SҞř27[brw~1ۦ 2֗GH6mdIAS8*THq\ru9   LR48sh5 %Kl3q;q۶5(^+kw^cǎٻ"   Pرc.CrE0{8zL>TD@@p^gEpXl۞e5v'9#7NN@@@@a  .g&~ V>uLuԩd_    q  2edKp8b &y '/ZrJ%"  8C3ƉV"xhҤ5'r&:2RjW6m4Y   +Z @^G=/^\Zu;~ERreS@@@Yx5^@Mdɒ2rH#7sX^4X2f蹂Î6UK^V/ZT>c   \;Z ` tQM&7pG[*UcJE+L'a =vY:O%@@@ x2o @{ҨQ#oe޼yrb)%'uWZo,ogϊ.$״vmZ~# X`.h!  ) <.EY< u֕ ;vHc%w܁TjIhؼH$@7 N!   EǏ# y@@@ \Io@.@׻ g@@@ ul@I 5q   xudh %@7d/   xӜ" y`h   rL)w@@G hW?#O@@@D.@H˗MP.]*tӄJ隐?s\pA&1̿wڸgf[髾F#`YB%jN|o15@gu8J@q/^4A}KÇ˳P),~IIɓ'E( ߿t 8p͆o>tYOܹs^߻5A;GqPkGMƜ?^2f̘a @Z M+i@  4u@̖-[=-,^fmנ%K,+iH8/]YgR| o+q$ӧML':pKzŷ%k֬TCLjO\'Ln'w͞={uHgkxo \9sHX/ jfx3g,i>w2*5^HivWv)p^ Gs/#3;WZf秊4A` @zL@U@^۳'P[G@@@M. !/@7   s:gh) i'@7y   )R@Z oP/C@@ H/@H]@@@$@:Ar@V o-C@@ u@R_ o@@@^  yCr4  Z @`  5   xC-  țL0#  '@7l3 +@7xǖ!  :jh, $@7   @  Ց \C{   ,@@A^   @ M7z @  +   $N-ڊ @  ѡm   xt` "@7]y(  {z @MW  x C  B)r@@@?LU +}v4Mpgt0雷5;YU?,bLT*U0_2Z˻}f^L)Zn nv=$#]CJ{ȑ&د}jԨhXgN:UXzŋG    a .]$:#S_KYAMeV\~K,)w>}{Ykn#ͽ< c-Y9Jgҥn-d~GI:u]i15w˗TJ+EW_?M,O>NLwf\m>u7m4^|&[jUٴi2 xS@@@``o0"}@T@g^nfΜYtfܵ!ݺu3:w׮])˗I[ːcMp|s1dӎ)L ]YH4w)iϹ F-`ƚ4Lޔ>}u' ԩ9>w\GN    C !0dӐΝ;K=6JYZ|СC4-A:KfM}ūh;Cƍ5M|R\yaiZYt@<:km,V@C^m@@@x=|4^;1cFӧOZjIVDs._v=*[+lݺukӇ 2H~}eVJ7Iy e)rIy$&w._f3;f~Ϟ&OpMr5{-]~$ꫯ Krn0mLA@@Ao0"}@P`\WW=z~[4m۶Z@M{]ʲe/]5L63=w&ҥe+βZPoʉjIu^L3TksOcؼER9+Ȼjʕ+%K,۩vIIk19}/}7͚530O$S&   (+?%;4@ \ų r'J.- 2 ,O95*?s+(!wOo+𠧞2}ܸ},X4:sFZ6Ӵc٭TEr=[g{˒%K'4T}8^@@@G ux@ x .omt!,Pӎ,]-]uk;^kѶ;ڴt{A0`h@*xP?ٺ-[T:   @  ! @h x/Ag˗ϜߴizN9Q8o(N=͙޴cGf֭RcYnz!ь`A~ߘ+קdu {o۶MN>9@@@"@9DBLP֭{U{1s>WA7]g!ok5-UӚ0eɜYƽfp ^ha &jdժUmY<Éqqqa^@@@ 0ױCG@ЙիW7\xjϛ˗Z)'tfnrLs[Koe%j7Ɵ3wd7#:}Lok5 &,Yh駟][Yb9Uo#Go8  8Fc"'лwoViWK0p@s([lҬY߻c W,i?؇|bgu\|Y:9~\Y~>BjTu>7C}7oN#k8-?u}?YfCs?6   X:.VbEя?#2g=c &CJdddPj}OfN=J{N"]F,Z춸NY6r^gtL^_M7dO{~tvoA+àAO  8V:I4ijJ֯_/sHժUE?jo>_sra_夕kj[oLᎃ2~sloiS/\lYYaoS˫]J}ɊٳҰ\h+)cRU\i=޺P+װmK.-SLZjɑ#G{E9p7uظq6wyM~ @@@ 5.FH,Y"OYAίZ/o4 ng{օUF_6n.ZX};9s?d奝0`dȐtF&MH%~eԷRXhEgvQXi-NXcn:ٱce   &@7F A,/SnRXD.=۶7\,AOuK[4)_e˙Xr-HΨ(o9xfͥ=Ȃd͖-rE)SԯY=riAA@@Yo0.}CBLRJi2!ܹsRuSeu`xp`B+ '@@@ xHdu5;jԨ$p K@@2R ::Zʖ-d߶l"qqqRH$빟ܴiٍbŊrm{; @7F>"  h>.p7~y+ ,޽{Kldު%:qFsVZ':p &  ڈ@O]voaj^gz%Ǯ'!A@{x8!@@@ }?OGY୷ͥ[N;u;+CnJe] o0C@@hphu~Ibcc%k֬3$… uVsMҥeѢEn:9w,YRW.yI=@\M !e:  -@7LJ!.^(~9[bbbImD3g~Z6o޽4m4;/"a}r ױ޸t3)t?^ }_56ns䱾 CTn{Lɓ'&+-,,,I[{_ Jjel ߯2-gΜ1C}_A BiU2!9 x֛!)Xx߿{M h9zjJ*T s犞4h "4i55jWzrCVZ;B\ΟPo.٤w! Alj5 ^K֠%nsk={LW; &! @ McpTo5]vg HE˗$\~ >0-Џp j]Aތ%s!,.aL?*:NӀfZK2fhrUYO-3BO>mԍ[@g~ӢﳴtgQ)w!gF5kɑZX1QDfbl3{t9fyЀDZAX#럼.i5$[\Vx-{ivW?yAH4_j`7I=Yd_iUMAU : N@p3f0YYYؽG.GE   Wד!&yfٻw]wu:tܹӤx.k)-:S~ hתL^?  Eua& @ ^<$gΜ)Zl5PG=xW\i1*U~x$@7F   &ɉן2w\9t)RD%׿d…2o0).D E=ך>hh2)N{| mڴ֢me2j(0`܏>7.޹%K/X &EU`@@BoP #@PٸZ/j|fk/-{ܬ>],_EWC0_pBf ު.^4}tywDsI={el#  @  [3SFᵺ@n-d@gZ+W?#]vy RΝ5p+xp|2m<id\Lnՠn߾}E_KYmQQQmoҤ,YR4J>}xZ({=SWoOuԑU#<"}],l   284@ ES:c0ڹe˖>֬Y3E}Mx \)>` -j-Yc.`=t5=g*kh kk_﷞~Ƥg͆=۴yXЩSF+Or̙Eg]nDDtXBvY)sه]AZ>Cq6@@@ xX@ 4ԨQѣұ׼YZ9J~oJ#9|\2C5f6:v49Oպ)-[Lۊ*$wXV=֬Z7dN{ҳ=]cIy bnݹsg^"k:}Ν~?͓'ku5-|8pc"  s:wh9 [݉'L?ҏ_kя9~\2[KzTnˮrZN{#>}͵Ӽ&c~Rs(53n5ńפ~JZHMKo4(apoR帇 $66k]]dVJ@*). 7%e,/*y̩3gdK,=q5,4sнh֞>}C޶:ZK[ky.]nݺw^ڵ\RX5 ZOs&U2Y>s(   \ 7 @P 9RVY~x]f-EWsKa?fۮISe 2OY5KH{pnA~>%\mk,}I&McxXy]{SO?3gM[SGnȗϤ"x |kp+o4<>eRbElK.- 2 ,0 9+WsREsXkreAR9   뜱 nfv=_yq.v6;"d^+;V00Տy}>j꫒#ٿZIS z)뵼1S?[ۯ'VN$:7sxҁ#Gc'?o:{׀09Nz5t˖-]X3*Tud&Dh_   )k<  r+R[N}mf=^zN9amemaWW\[\9t^=YzNYnoo)qd͖bkViWCޥpWnCVtm>kv+֢3x:;;wX);(   \xk<  4GK|ފ.S9y| D`S;'d麵rQSI9+'RV.'jc#3#YRm//}~C(}<^ 'n gy#8Er] g,5;Yׯs:㝂  %@Ozn+w-[Ϭ|jkꩫfUPc5],j{(w[O`ov-@@@ B@ $4Xk=z9s%wjBYmڴIx/ʬMݩT,_ %Jf펞Mؔ燾o"l4n:]Mf[sN{q#Ǐ[-V.@HU~Wb|s/,qk7;RwZX.~4ue&͛77GϞ= ?u8lOnǎü"  @  + @ tImV4Xe]TC2{lsH]دKceh>u6mǎ&:O7sL抎vҪسx+̉7uҼ3Aٻ=u])wҥ"kڇ'):Ysj9m-Ԑ2n ?j pk{s&v23y55Ce„ CHkֵ]jԨ!36iD]'wu:tH40쳁3vyE@@ Y?L\'  $SN?uZ6ڷo/Ǐ7BSкxϫti~W^XR({gv4/_?{g&ф8\wwKAK, nAI,!hhA;Wϳ33]o}S]}|wm8h\;WKпM[׺5R6a)$}m$ @\.5Ϗ&Mmk"E{_V6XZ5u!fsgm싷\[z%3Y$最,){j|5z蔐g:9Mx 7sxыIw(jH`ٳC8 q@Hs!Lݻ7]aV!L]O*)R 65w~Ŋt˕1zsKPߓ,L1$sUnjkׂV5j(Qs5ȍ{Xm{toV{`I6چÜVx]an˒6U#'/לy(Zt7I7!o噼|c_5M6y\Z"x3@ E "xEI-Z4"Dyf%2QD9˒^=N]|YQ,t)uv.|LL79ի,QeK.Dz#EZ;d/Ǎq Zo-_u_QT)]!,̕8pZe'VҔ|7tazi=2sڊtԩPܕoޤz_/6eJ*+JJͫQ+-T$L{eʔd     ; XS0.]PttUbEB]'Jڵ81cz-(i@F4kWzltn.so;uuYI0rH]uQ @@@@@<d ĊV^Mɓ'wU|hZ~xSa)hɨNS54TjM9k|ǯv*l׎U\TآZ5լ.q>Q!5@LG gΜtj8ŧNj-J͝KUJ !xJ^|s5j֟Qyoc'o+y``@@@@O=%7|yj     CS0-Z8    `.x5@@@BDc3@F`qZ0F8    `^x; @@@BDሳ@PqJ0R8    `x1@@@žDްg+  A@@@ @    #xc @5w    >EO 7P"7@4     Ck]y}w9a@5P#     zᠡ    f"L _@@@@ "@&(~  F&K0`.&Ivjޙ˗i겥t/\FSt|"T|m"Whv#IԽqcN^H./9sRf+WŋitJ({K.5kVmp@@@@DF ?~F3r /0_޼y;+VЏKRdE ' Өٳ=Kڴ6~?L?Lo߾4kJJ0!~"˖Rf OGՁ"⽇mUcIPwEwԩj*ț7Mw$c֭4m4:t(+Hv@@@@@l mD!b(_|vKBgp/4v-ۼe>ۧ9}FsDgԥDBD!-Ӳe4l վ|Ѣ%GNN]H~=K۵&Qܶ"o[}v.ViҤIN@@@.wwCͩtt9m=J}#GRJ8    f!,# ?@@4HgݻסѪ7x:~߫}1-1"Esg"*$eAAhc4ebRg3>ȜΙO?/ƎQ+(AO͞>=U(!mPs |k0M-NZm<|Gmtsw/Oچ"{ի aCժUuwGD~)q7SL$qQ廢rʔ1cFqn    Ț7  >Dۂ v}a=,IWFY۲ouQo<^-=K}T_PmFvm1e={pQ9뷭vdQʭ[JԶUncI0e "͛v/= ~qYD-I$&j;Ç׵"@5ݐ!0qF@.9v^Oĉ)%/frr,DfS~y@.u+3ԩ^=| ~=O/}Obr臯 ^l}Om@p jorN3"/WlԨQz֭)6"krk,Y2up@@@@@)0@LJ… c坵7_#NٯU+׳'=y!IU !eJ³k~[ ?x@9[D]{®v-*s&tw#'~[*Gvv:4s̺h۞Ip`']&Zsׯ_SܸqvOLܿ}}֋;600;s  `x$Ӱ_p$+Pbh3% U^(GN»@[4+*/,Kڭ%-_*IZ4'PuD7mOTh->6_E&w]*~XUL^=iڈ>9J}єM(+ 2P-Ν;!y>h%dEb^v-ݛJpiE֮p? @@@@|"x}a#D`DxyA =#VL"DOҮ]kѢEO?|Z3ѻ᪏qcŢ&*97 Rm;S-{bGxWI'»y=a,X n ǵQ*5yxoքd֔q~"7  `rXpfzlHmJԮDJnoΝ;G˗/W9<2^9_#hv)>9i8<}J]E=]:j[&5*:{͚Eg^[6Sĉ{5lLsNԩ)a8!"-KKpӠ( 98Ss+%=ϩ'z'miX^"ҫhhˆThӦ +WrEWJL:ݻG͛7[RҤIչ$uhiٲ%mO?Uɜ9sÇm,l/^\\A= ׮f}n0 77 @H >lnj'# Z;i+).]Jrdɒo>%ݻRHAY {$H숨ԁ6'!CCԋ ]dhE$"e6Uz ͝Gydъ˯&N Rͻo,Ij &?)v8aAڇ'~K*MIߦ- {GGELi;s@jVI)Gb1bĠRJ~x'mt)̊y؏?}Bƍ˗/ӈ#A!l2]:.Q/V~ڵ~7Na"Q9%ʷTRtmȑ#Iې4"Tw몡#ڣC7 IuF~1i+2>?@^0O|͚5SC@"x6@ B@-䟂ɓ'S"E=Mk?eqn޴nU^ 4{`Mo?aRTy3zfj0i%h/Ǝɜb5T GvTmpfpWn9//gGm R[Aɣsz'm=4ڕJ=)yrQNYnz 7`=jԨYYȑ#۷oE ^ g{os ,WK$ڶQp1r@Ț=p@PB*Tl{vs~~5qcݺ4F;.Bfhc/6fIVE׼l~Np!`s!lfo>zV5ܪgc)S:$QW,GkVfM[תU˲{"p1El@5`EsʊTf[&%:҅&r7OuV~'Kܽm_זEJ9Y͛$ y{6/%~=hW,2R&bwO꽆iҤZ-Y ӧ߈'%NX\00+󅸘u&IEɳ+u,$1cUq^;Cg3x0)W>D=c%D*/l*/T%)P흼Qr>_؞Y}͋DyWP#^FX=iQxI,FhOxDYV-}ʔ)Zʔ)ջ8uVVZC>Q+00R8  p ㏕3KW^6;~8ɂWb9rRG"w+vqҚ h1 u蠺5s H~?y#}KK|Y.[BkZر"1D'~K^5j/z/TPڎaE<ۓvaS3i6R~qO"yE^mƀtO"sϯ޽nϰ, eϞn=@oA@LJ@Z-Ro֬Yt={*װaC l=d0=xHTË2XvgZX9aړHFf~6r/s \htA"jmB>b1P<_%Jp{νaNyg[+5xtRUֹs oWXL6lڌ3&UZU;w0R8 !зo_Lnܸq('rGchU1k= iב#G˗hц?~۲E5H;}5חN3cOxf;w.I]N֬6G= iHȬm=Tg%3м'~{64}p\8\K-ehZmS6l-j'ON=zr Y\-'/4(qFh=e[LH9J    f%pq0U#Fe˖޽{=:oӦMiܹ25GJU+d+hʕi&z ټ\YDKD{6{lܴ?}dcl@,S߾}joӖ:խK+nN iY oCHrIh:a|e:X]2j)XH byX<]>FwjhŖtEz-eNj.MYӥ qG0 ~Y,5y4{ZTDwrh嶭j%m i{1Gʀmœ~z?\8r,h9uO}z5uY]ɽ?WS-[ӧU$IP޼y0d9i#I&!,5j v/_ZF5 &6"޽{p9'z|KhXaU(og}I Zrnd94Nc׆po=gDytۧҒ    J<E\;t!>|Dr~/{k^MamسG-"-9\geqEmoW @uDJN^WL/okпfܺ'#VvLJ7kU>ixO    'c [QdPL+F ]p N0vӻ;m\X7pLJXbqpz0& @@@ _ٲ[&x]Y޸\uuDd}WN*%I[C?A@@@@ T @ U8@xh֬ETTw}Vɧuw/AܸTd)Z1YDIb+S&*=FX<)ujݫG?NZV;fLs@IQ@@@@^/(t@@ $VZQ…C8ҽQcʒ6;MV*IR]ե+ō[W]WEw3u? {2;'^(RHN#tqZ*ďO>飼ӧ^    J<<˗ϡ7ͪTo;urXǛ EZNE;P55}B޲ߑ,ZԨA;+~X~/k$R{1h_{2W-Z:N)i#A@$%KF;w#FDY[\iɨ4k@HH3 8ԣISJ`qMDEiӨo֖fߎ,\H-U "ƈ+OB*Oa-\D7o>,SGf鶤ch[YJo9na;~2  '}OYcƢo4@@@@\&_6[8! eh޽Nj^۷oɓ)J5兗|W{wً"Qb޽S,#Km#7oݻ"qbObrXyz߹CQ9]Nozx3W?Гvšw)6ߣP#D)RML}mϨXR^dQÜ#NH ʨA/_TEt~`0aBPAիWt=KxW,ί`}6!  D8J& =|3 DJ®Hܾf"dKj_1/8w&IԂE^_k      A@@@J@D^k0_    aDoiA@@@"DKD$I}yC)    `Xx ;4  A@@@^/@@@@@/zIŃ8! x;>?cyA)WÇ΃"W&T>xocw@uڀ^     "L @@@@ a#7XJ    aNo#@@@@ G"p^#0 @@@@|D^{x   &!$ 7@@@@$Mph    `x0 @qu @uD^S '_!WF~8'9#0t@@@@ @!@@@@@j 2@@@^B8    & V@@@@ t @ ]8@5h0%V8    j J@@@@ @ }8#@5ۈ0 J8     )^@@@@=xV    H"/:|CkA@@@@ G"_&חGG"{ @@@@ @ u8!O 'A@@@A@@lX|9 :RHAVU%ȱ7юÇi߉t#ʒ& +\ZרA~~P:cHVGyJ:~BiQ!ʜm[w҄ґgU MZAU o,ӡ3/Jʚ6V>.\ذ~s;m?xi~RmٷXA/_H"Qw*5ߏv=ĝ'O/ E?#GRXag*jBg,YC޽\KMLia-jTvQ:uSyu*yZlI'y 98+@@Ԝ#NEuf"|hREr#ь/vlmV5g6pM[M~ 9봝rJܵSEΜ: ̑QzўNVu%JD/B~K:I-"RѐS,Y[4Jϔ>EJj[VDz~9Оܺ۲zu[<%8@JEe۷f?twd(i„v=zEWHѣEU۶ӘysiGg? sA=tRI(B7 a_zE͚5#.;@ hÆѸYJܕq_~IjױT-+7%K@ݾNE>OQhqݭ:}&~ިbQ*A^~"+ntW,OOe!yCͫV Na^N"NB;KD b1(v۪;zJEN1~o~c]2_~ʛ5 5ۗڥƼLBQE"{*G]M4n2 ^gH X6,A@;vCѢE2$rUm-jZUye;Æ{t}&NK?*]G[m=[cBTs\[5R"jInVI :LjzbD\"A]ͷlS@QW>(EJ REgh~\O 9{+/M^Ⱥ(Eyu]PЍ3J޽;+VL!C vk1  ` /9´QF$ "M6;LfX1bОs4[Wu"Kݨ7kԾ=DL64b؞s\[䗘eIKp?D1Wx:nRS}T)[9 d181N΋bۻWU"csRAw jor^M^ڸqH^"p(̢dɒA@@@LD |Ϗ9B%J^z9uuS3S=MK9fq3"*|3e6-΂vM'꫈pG5][|*[4ټX\/YtR~=ˁ@_s~^IɋU2"` ȩ꼵9ġ]hG XszğM=&$IB#y}|Ν[O301&\ f!i&;v,ٜ^ rd翾n[/k6~Mxmތ F 9GmG!7$xA_ǏUqfIm~7҆ݻiA9LQN 羫~Ǎ⃤g>ݹΑ+R4HѼa)vGZUj1p ݱkWIDNDyC( /ܦ˗}!joiєBw[<^HNR-hтܹcuԡ,p˃,{@@jY%^5y=W@xkW9N[[K3 hExHfeHʣ~ 1]'}ɋn<[&ZD}L.,o-iKZ6-¨fN"Bnc}Qb[RKhc͵ڵ.ݸAZv;x}f5{䩶PM7?[}CD^h$NS.3fL/nzj;w.}ºYf6(@$О^vUFZݓGΞr:s:ׯO 1_ty۷S>u7*>s_RU]V5ѥ~k'GG ƞp-Uõ۷i]D%JPmO`tѹo޼A?MtaqcKͺ5lH@w;k"%otRڇxS|"xn<FB2&}qFwJгgOu޽{4h@7,֦     OT .D-ZH囜6mKnbDl=;fL?o>Mѓ|)}m}ٸu~yJms׬7i}yܥY+WHAЕE#~Kʍ\үN)9G7@`Gs*eѽ-[ptdC!=!O{YN%OmY~@"C?Z4C.\!KjN0oPKpaJi dFq#U_E© 4{;m?ێSo87X}vZ- W$L 9O5jΓcڥK%     zᠡ L2Q)9s&=ȩbXԩS]YTmrG<"E:die;"Mw^qqz)-fBUmRS}xWPߨ2 1~00Ըree+l* ϽF0O._(I9˴kKqJ6gڴaD`|htyj`# SlYKj;vX$ H$^zm|:'VL}duB9%BזժUaڵk-~۪c      >)^yjLOdM6%YK[ǧwQ&MԪ2FUK8j"yWE(eQR%U Du+ORթGK$YDD1m2NCqWBX N1 aDT(gNY33Ǘ #\E$S*K8"~.N'NLGٟ7Ieɳg꘭߼Cg$lY;V{]0pD92Xj?~̙Cϧׯ%dڬD"s2V29iy,%ΟE=<[nj;EQ~"Fw0-]r4pqNOU9~HCp< no`aQU,)'9xU?mdcND 9ȟ-JԦK"(]!.BzXl Ϛeʒܿ"y?YCLѿyB)Rwo&YrKWo߻OS&߱߸v$ /}y-E9x"x5x99oȑ**)E:t(IoIS=2ƪ>3@}5/-ϨD]keRWGBe"ٳ"I7vĉ}'+'K>5^[-ڤɻD7e:T\9B~? ,UvJJ5qWw;jV"o^vDn j6}Nݸz׊P*Ul2} u\nb8\sQɶ%/ew8 :u%D<'ыݽ{vM78Gk)(W\6m V^%=VWzXE^|JD,e1xӏy?ztU8u"-eT~{hS9w?pV:r3W) ~͕~w`!G׫P!8֪xa䗨툴۴~.zQޓ<cHk@+D[W g{#4AOzM^yQ0G₿ͫT 6"wʋ,;+J3獆3CsF >G 9DSZ`\I AS Tj{ Eܲ_ؒ%K~*]O>*+2b]nQj6`%EjA" ̘$S%Y`,ktfs/?>L rI~Jxȱ׮R/-~!S~]{5 \;e2.Ӯ-|Rskъ"ϞR.t$]m`Ɨ_C8v&M@QX.`.nr ѻ76g^ LװaQy zw @@@@@3B(Y_pRm/ Ӈ+UZr@e]9'xagߧHӫ|gxz6O0AE06lؐϯ[p!䜘"*?DSg%J̕J=j[q,Qʯ^g(qW}$'s5,p/_PZ>eU(OnVup么f2\%Կ<̙9M͚4~5>dyϟW*}^ Q|ӿmB9kȏ?2f  `9,&D 0y iGZ\ջAY9lN"s/bYxF#wݎt-_ U)nh_E\ؗE-ߒNa)y`>n#Y?g̘AkyE 34J.M-[ $F>8&1,ʵn:V2Md 7,='NH,I_gζ&>ҧO),m^q4!ZF*UڷoORu%,팼е^dM h4ͫYi G,KnRo3:|;N/I!ӧ)Lh\8WKUٟ3,d"isJ}Rp&Ie/qzYXoꘈ8/oQ+FS^b ƥŋS5T$%N#cmK=jU:]dEt,} e~ TF3~U֥O>߿QwAB v@@@@"A׭h ^L@TEԕ,y4hB w4j(U.h QkVÿsQOjog8jٳgI|;v.;Yn޽nCOïZ J$'*i ޲H(QFɯ:{YrjǃljvϞCٝ<T$F$8p*8Y?'OT$kDCcoOYBneDܕϬRv&9%W" E?]{p>yL- t*J[e     sIz,l:t(IVK+$N9x5Wr2JDiҤI`:xSV[MHx*9Je! 6f\ni+N2q=%*^?-QINcV)s 0t>XHqƙm    !?ۣ9x0)ڵ+͚5KW7D+o[ȚEծ&j}7b[f1*Gst(s[woÊ;~K;NEcd1ZP Wjw>j[ԗϪ+&9;֕~.7:Z/vxss  OK4˫Kd, Q^=Keu?8ќ9sM6r{ZEe駶Еdoxn<-ŋcahN²MX9s׾= A@@@E EF3xa){&yy֭K8͛u ҳ,$WgZ#8}k.{ɓ'9Ρ$Iu<-6nܨ4eIUke vDR{ЪWE޸^^aa`ApfCоEMQ@xFXQl\J*D3Vݳ,&CbiW X1`Ż[B78Aˋ2S最6Hx 7sr&&ѣ;oJ50F0$t @ȓ'xsIʉ%Rg?V|LrXlku־}{o Y*a{,Bx>S:mdɨ2@A"9rdt]0*%WH֮uRSΓVfk1,ޅr椿J*U(Q޺N [3 ~eP 7EEڵ {~ji?7oUw϶n%/7֜M3{5Ûz   +[}0I &".+fOh#>czܵҕ'ҷA7h؈r3d~n]Pgni=oW_D:IPNb|o Mשk)]4}]4hЀ*U.*^s/rӀz"b":J@[츝@DKf͚v)"NUb X;{*+ ˰Ibvx[@SD7'ͪTCJ}᧷HƂ3iZ~T2_>3!U*\>^D2̘.\H͛?[v"J:[+E3<ʧ>{9[t?"K ݻӡ_~%yf>d)u]GE48/] jp讍1B {u.wܡWGs|r7'j0{)ɂab9'zl G*+ >=.yVK"%OvH.\$H:\qy}   f"L _@@@@@@/zI^C:    aH"oũA@@@ |@ θ D^c z   : @ @@@@@ vh @5CpN"sF   $׀.@!qQ^O-D^(09&`    .224"7     `dy<:X@ൠ@y^#     F!(#~MxmbA kA@@@@@ qT'  @@@@@ȫj@8 kR   7oдihӦMtiJ4)/^J*Ee˖uzΓ/Ҝ5t&IJGjצ7R73(EĴjx]{1MWy]uOO䥪-s4}4mr޷/Z4x[y*vr=}8G Աn]J87鳞=ӠvJRAwӗ/S҄ =^*>*[pFqo[Wlu(R.7 k>ׯӠAJ*5kmYlذ!}և    'C A@ [F :uőGƍ~i9rI)/z$zꕥKh4Y4gC$4,x2EJj?|-HS.Rt靝2]V'+چ17Eއ,7mTgT]zUuwWZ5TYjТrk֬DkժňCa?1!+H"(AܸtŃYVjE{?Ƒ}&N,9_]|h\E՜;.޳Z][RUw߹Sעj sL4},Agi+bu=ȱׯE7ew8?zt1ʌʽm];e+V贙+ |ցSgP@@@€0SxN@ۗzM"2Z'*dSrYO2%県,>-;*ڸ}N["nz  |ydqme)^PΜ$ĦsU5pD,2&~?r8+]ɳgʯ¹r/g2kD[~=:J(W;hUͺ!fLUvG+~{%x0wA]`͟?RHA?hor^M^09G/h  DiԨCϜ9CwQu*T+fK.;XΑFoLVsEմX͋t2Eߞ̑3;I`Dso_xqwX||d8AJwyvkFxQ2s |ێL}7T쨊J _1wp\W }$BTfΜIzrjo!?NW\_'^_?x)[V-TRQmmqb{۲,$qFMk4uT@IDAT=p7TL:4yyOwT7[9sḧ́I]o3w5*˞M_\IX/2wO?7.ρa}|̼u~̟ݺ}ӜEhK uX $ʲQ V =;PN$,eDc/!ݩSTUi/"]Zz5?blO@O 3sغu+9VZe3[tErRN-¶lt*wDR(T-UZհgV_5;-;0'&z"ISHDTiTT^W  4AJ ~3݆\HM.&}wߖ\;Z]3E.=4~K{) f!E<$‚!CI ¹k[Wlۦ]N%_Na6oo+^ad+QW=6G/ #s$C,{iۥKڸq#]炒{ݻsڵk{E\A@@@ @ >(Aމ'kq9*wĈT#vR~jCfLWk`qjPJ(eGZhbڵl3W--1upfYT8m=}yowQr/:NjnǪxSӤ'S1؉&A-j"IG1rl*԰7O6zܿ7D#z7)JTipD-Y-}) Gy0!nZ1XԩUQ\|ș=zX-3&GNƧG8kezi{Ͷn$E]?a:׽[9~<a"i[۰^zٲ$/ͺ4jLڴ&ySGw:oM!p?mbt#soE,JjW^yc "nݺ:7T{;:n A@@@ 7  LCQ ˖-#_%԰JK7oR)Sj&+ѷMGW._>?z>dLF5B0\Rf=F6˩'(qW-_M҅ {C'.]r>{p87[vK%R,kXO;y:IK'v*•mm→Ye_~v_??ܤIT3M=µ,'(?TKe?뷿=[;HW7]C%6Îu-/1${voQjȗ$jIc~G'J-ufvW믿(˪UpsL^zI;!q$)ӰaDtDqujTXbŊY̅pƍW"ea 98>Z׶>gN6Ntw9 M(]T\8kjk)cRDם{hѣ])EGߒYwԨA3"c}wt}}Ԡ!Gr߲5"B~STDz"qU9eDPwߵCNZr˛n_aKjɩaC8WG|~+=V={*RG,Ad0;0O9J/Rvrѽ+.F1   ABoH F '̑#:u*jՊs10[0 @,` ۴gGD<1|,Q4rf7JtkmScQuZ}}1]w׋(bӝzyat.ze7b"8x8bpyf% ՗I Dxxx.٬Y(î]hŊj/    DD%0x`y.?%Ww*wMd^AQv4+BCbFѫ }:rux#ź5i\ag9e28-BjSI"X9?$JèQ  8 ?8|I`m*7r1f-h&E [ rȼAUa\Hq.qW rʥuԉV^e \@6GF]Rt-r|P P8@@c.sN4i-ׯŋ\bק^zY\%#Fҫ͚L\p*=enN; U<3jL$+i?+ Sk2 8C7T"|58PM;3[w) ge߬m~˖}8a㊇oPf}G# "o'AR4-[V%C޼yǏ)ɓVZe0b& xe%'NTCvvJrMV3>zh%icÑS#Gh޽ץK%abEjǍ$U#l5XԦ>4޼I#SJѵ ЀVkO=YI"8"Z2g<]w(Qd@H%2u ~$FVضĸ_w۷Wל>9uh5=A菻Pʕ-mٳ4~baNr%O-Jmգ׋>7h~ߋ̒zS8v>7tbŊ*rw֬YpB:vzɊzA0E1aDIP>xHVWrݻmR%(| Ttպuk7oĎݺ+q?}B/ql28eiwC&ymz YZ]L"B.N ۇ8M1fQ<)'Y !Eiis\+9}n2MG߰_syzӤ0Ç.2kyy$HcgErQaf4֝<ڒ~$ke2]tiZ;/~w]결a &opUvd\y%s:f/bv="'r%3L 5݋#=k m49(qs">v#߬dѯvsOT G}O> LJ… ;j    rPd-9! ֜֞~< z^NOXة%v!9/SmV@K gҊiN]7I0`Tc@?hVC:w5GW}} 986퉾v:w駟NxNs0'Oc)B5Zp2kR]67m;OJ:@OA톈~ypm[˺ݘtfn8o鑁g^`fG0̜9o    sx};.RLjm3 ٮ/^z]n?xP{36}Ij # ~Ar8~&S5귤@7(C a۶mfu)$AAG ]}˰ o7n I9v2 +ssmx Û7 $~h      遅[  :z 6Kʐ8]α VO*/iSy+Ke쾖6m`p>@m(!_X]V,QP{36+_솺 ~R%ߐ7ތ+7v&O^Νیsx|$Q"C0cc~W,QҌnSƮU~    ` CwA@㏟p1*Y2z.Z5¹rQP}0~xԦ^={_2eJNw{6̕% U/[Vw7h@cެ ~rgͪ{F C5ߦ^F.;ňC׆&LH-[@@@@ T@ # ?A@  +W:u˳Sĉu5{kզj沛 X3pŌ_[9s;C44[7^(OSD깃Q\Np$jojSqڙמ͚QIlQ[ɓ)}ڢ *G ~@/^,91%ngS ^X7Pg+'gVFQԩr< !?NJ h: ,ÔORs*E?LD 03W bXsoӢauG_oVJ jb?uk޾;o?־=ŎˮeրA*vc&22  #G+Wݻ>|f̘A۶m;ׯSXTljUIT\ڎi5tqze <_z_X@M A@Zu+-{:z ?$ VD ëP,Qt:v}zڤ ٳghzZOt9QrV7˔e< ybVyGN._D|˛լI"]kr7wL'OÍkSlقm:m7n"HrSҧNw0:gvb)tD;N,{菔APɓ't^ ͛7"&g|>lڴܹs;@0LGZE1ϝط!^y?^9 #{ܕGZl7g-ym|C@z葝eKz!=~ u)&f17 n7 '|~:=NާANzdEڵ)} ݀x^oA@@@@I"9 z   `^C@@@@@ @ g@@@  @ ţA@@@@@@@ހ;d0@HA  @5B@@@k f(!z6.{so &@Xl@@@@@ @ @hZނ%W/)#~]D^ t@@@/pF"3:X   g@@\xM>6mDǏtQ2e\rTR%6:cM_ ۏK]lo={R)L\T+.yיrZ*yrʛ-*5r}5g%Kșt-z@2QX4r~=vlDCgΤ cm泻'4`T~MvnZ?tmHR] GNsQ:mȝO[0^wcyq0ݫHCO.]Dƍ~N>M2dSVp†   I l'#Gʕ+iuCڵkӱcnm۶4i$3&?tyž}R jkJ]5z ]mS|>~, ɻ=kSMKm\ڻK/V‚r\D 3p eIF/ݸq%JD $g<[:od9g:Núh޼ >=|P0aB'߶p*j؀n޹CYY:zm|~+UT#F cG6w֬tlJhFׯ^ΟQ>#v4GԣiSE~lo?Jn٢}~Ք4~|I&յFtFaԾ}{ײݺu#F.2{@V/O &Fn0n޼I=R SHAZ5/Ν;W~@@g3QVZ*j7YdԿ+?DWZEGSWK.uRΝ.Wa;Q-5$7iԿe+-I>U?D+۴tz6v"m^+R4jLfoJuڻEg̴+Q0XOX˜.=;{}rЦ5}?q"*d7O=4"68g֟==^Pݏ+͓ǡ+"p<{?}_fլI`kWɓkxʟ#;z9Ӹ߹2g̞0P,}Ԕ/Lg$aSz饗hȐ!TX5Jjٳg֭[{]l@@@   D'p֭[GKx ȏ6mвeTo\,˭'}>?_EZ/3"JDjB=CFj;|-"^͖˗#3%RRKD,h1h>t&/_F4Ts4m1 ˖5cYIRޥSB##zIq_/b5|q u{|9iG-+"~LhW) Gދ Ꜻ&gkwd!u">SLnxSy~]гgO%C]vwu|(<<*WDޮ]Rf(nܸ   Pd-:\@!E֩S'?X~6; {p<GD3-ݸAuNŊQ]rTsȡY%_SY,6nj`YͷYewlF#|GqMl,߶>DDoNPB0E:Y"N317H]2p&j>}}S֘<ۙnUwi3[w5jYh]a{y +&&$=߭c@@@  78@! \߾}Տ *D&IDB= WmEmɏުA8YMW$/mN<ۺRtq>sЁp^eIaFxI'"R4h@1wyǖP{TZzQz[vo=u.(H*(Im[rɫm$#EL j&y`a   Ko{x & "fƍ x^3@@@O9֭sQVtl7G9txv+ ǑI#G 8jfziI1i߫x^3S=Ua=IE1w z 9^Z5IU 59O.UO%D[]+/߸rJgɫA[J)$%[p,LᓞN6>L3V}lڌ Ifu7툼v;QFJ >\ËM6р]{@@kgϦ#,NJѵgkV \R! qN?1{tiZ9wR Ͽ?}ڏġSHܖ>{+hѣi:˱Y EZՉx0`4R葼9G u1D(>\̻8VnD 䬎$}!ڕ9n3OPCsZߎ8t HR|v wmgEM"hтCSN\$DTRyg*>!v.2:jԨ(.H~^ f۲O1IW!B'6OT^AӿK׮Y͖2ImlV3w[bZ5y&/튷u02Ӓ3GV(QʼnK{Oy1~0|Fʞ!\GA~$^-XQҧJMO˗}ڛҦL1;뷽\zn߮I<29yL$UâEܹs#r6XB(GOj*6e*Rf+,,]רڛ4];\D|ù,b->]y$Dqߺw~zzU{)2r1a܌-fͤ4nD }sbǏ9 &%9CEv맽1o`Ηh=R&Mٲ!EHZ+ AZCz͓uN:KF$ɹ,))*MTe,jy'Gxh&",ŋIҒH*#FPx^h&4F<;^h3#gH1" ;jw9sfz_d ӯPNRuI}Jbk8^R͚MK͚t8u<ϑ2s׬O٢b4!{~Kd=.99ϰC&[ҤIm72Q w)ktR+(Lݛ>s5koҤ}dHܵg2V"d t ?rnMMzS0RDP+O#sZ7{N\ǹu sZ1Ӵ~KO,n$OjfW-Iar$;KhC7oEy?wZMnSG=ߝ¸fR@Α={jq ';~;Wqzrʕڽ_&_58ZIg$7f2==Nw'71<$pΆ Kn؎;qWL"ݤػWQ,Qw$CE"b&U;W"{0RU}XIMzznBu~ǯiO:2lL5_Αm뙞wסߵI*RN˴'^v5X)ߏ|rEϗυU~^-5CVi@֦l4z^N;98*[]|)eN GDllwF~*y2>mּJO^~rO֟&E4%CTB"sI/rk׮eOQ8qhĉԚsO1fb"Lғ̺ͅr fn0$Qȋ|ϣ |eRAlܹ% >#>CC@~VTvJsj%K=z">#U^JM>ȡz>gOV_Do޻, Ufͤy|y@w9εɗ_LBu*V'N"9}ApQZ zAȔVDKRWwrgJV^;=^PNO8Zu%eی DN!)e>"=ժPtH-f`v}%v^jv͞C͛Mڰk3%?ڸ1}À?}jhb"z}eҨ1] 挈7v:tݫ)j~hZ][K6=Go[]dώ^{j7moٲў FԵ[eLX?ab> յ q/v]fxm;)E4%Zwm]fi߾fn/:ƹA5 k14B0#yw9AԌ~iWMǣbmhR$WqQ{v+G#Gweej$L:S(c=z|=MMFY@W?%-òu`Fn٢K&.YB776ab]lW^*%@(JG@|zZ. uN9W\mfmxMH?vTެ~9tHۿ7ҝ{67m;-Yfo3wjk\߷zݬo٫{|]/[c=xH`݆Ct%ҹ9QHo{3 ~A;!Nfllo)D(3݌ޣr2+I@{ .jy^lzh     1  >}qF}!!}>8;owYw m Z](v#|6~/˩K`    `^{T0@@ĉCҥ3Li7q5Θ6=ߙҹBoj̘1),uj/ o}/!{5$OAR҈eʔHs!xC`U6ժU3R^3ތS$MJ,hkUK6ތKO)%ݵرb%_ެ _-E1bݽ iP/noֆFrŊQ~Gm#>nh燏ѵ,{<]A# 7(#$н{w===cFjn\w+,I% ެ c`۽׺n=C MzK^{6mfHֽa7,_8.\X^\7ꇆMW'9zLb|z K@IDATǍQqu3MZښQ!F*U   '~s-8#P1c8k%Aq9C0X m.]I*0e@i bVW_u¹rȎ] _~ ͖ewzujߠv`!JGvW>/K Swԫ̔eaa4>.+a)ID.B׋O[pb{ԟ/Ӿb~Ք"٪N]c?H}Nkϲ)S 5-3Q{8 y9O9k6Gbh!FI+Wݻw Cݼy,YB?ݹt[[e_'r8~>~L"([*?ҍ7(G%H P;{mHGNreLu*Vߧ}%d1Y^݇7?mSϓD3̙ީg=ǃH^8\onaWu/hݎK)r%JXj} <6SO[ _"W+wĉ#._[+6HPڔ)~VjWhhޟ4@Q9K7l=G=F2qj_#OlV2Q {0ǣ^RL6}6X     ȁB7A@@8ƙa )~O/-[)Yd… iJ4iŊKWN<ŏfjwG6Lkc  / |JܭSuղŋD6k֌>Lk׮~۲لbJ!C8ke   D"o0M  Dz*={Ve˖/4]tTjU5_"}&"Ǯ^bh  AD@Dދ!  M}= <|$rW %Mno'O߼yr{357O<c@@$oa  B G K,Q2@͕+/{9sF͗uvIǎS"rΜ9Xb  "/LE/A@@k f@`8pٳGuL2:-)D7.uܙN:e RNFQ~x\J XeL/^<%jz8n8q`؁pH7jo}GTR hL"qõ-h /N-` XXi3erZ9䞆O}'Ҿ?#C'<'z  ~gAp .R)$I$Z$MrAGc0:uEjyؿ?m]ݮ\/'Ka9%qǏO $xS |>T˅,7 $w>MLADMi" 3kpTKguJƣ{b<9&ר/{e2LK%;W"^P>A@ V/RE=TT )h1D   |.\$y7-<Nx+ #tR0aߧ֭[6n8:<խ[WصVfjo1;~@D']vYΝ;S=rT 6e(Q~M 2 H"@@@ T@ # ?A@?>@p AzTjUU̞R: T^̙3S2e,6vA7oV/Bi.\QFoeɒŲ?'$9sh֭c9`|ؚsiS<lץlFw(|}ȑ:.ܬfKsFo{d*]v-Z<$Nԥ`Vs{k Y=iOO\_>)JӧӦMTtҩGʕ+Gjʕݾ}dԑ˧֯Y&0bpц a @@$/^L&M3k,K6,dI4pl/Rmڵj^R(w$"JEҰaTѐ(+ Xr%޽Z/6BmM4QTG^-Eb;Goߡ)RPqci4A%T:Rum?[YBTvfӝ8ѵkצcǎJ}n۶Q_~jԨTn@懟˗]Z5)("k[Y|Ydiܹsu@@  7  z~w8ݣG 3c AR6%HZj"nqԩ #oE@ٳ'UPAUE_iȐ!tE,tJD9[0`Ҩ1Κ._A+7oi+VO{R^hu.֍tB_8ACI$r>StMXX6s',eN=CJEUhӚ8J*l_=^LCS?\h<0yYs?)2݌:9x~5@$F._wXI>ˢ#>)S(Uy+{ XdIݛcaG$ST#w-9ꅡsVK-XT;^G#GI_X,7_GTlYZ3v\ueKX nNY0K'~Gq2{w1D33Fzw?S8$"{߂|"xuRZn_rWW"_t_/Qrb*4^9&S̝s%H8<` we9UTI^޿9ulR5-Dܕ\y`7ޔ:msΊA~m'NAܫ]?1HG\g&)ȴ:u :"JW1{^}?y>{_FX2O"U[#d_0$xh  BDw(^yaI$f' KqU!ij_x/9Y dh=L{sl&E4;ryeH.]CÆޓsB1[z<ևO֯briJ޶MS%z)s@cgzt}~6ore:vB=k::J|roݗ͜EHUEsF7'O~)=X2Rt[iNxzmk3R_K*me6^@䕇}U)Dȵg+yt$IX/LI &`   D@@H@fJ4$fٳg&{wXjY`3! rh3X.8re$3-m.#aW޶d)%GCpw~[_1\͚CSf5O>y9n-$~;O&9o-}w<>ǥ`ȇ9^u*I!Bj&"`8={9,_6Ot XnvNðz5k[[W$gyQSG3'`   xq@\ufZ+…$?$QYG{slƪobW!w_D}P-n?->~0LnWZ5c(eg[+&䝭Ǵ~5[JYd}jUg2wOɫ-'^cmٿvpI-8ma~َ:=a2\;;ke݈ j 5SËM{vӀiS_u+VT9ݽ&ȧ+i'<9 >5;"KT)*&QYby3ªbR    @hʕʃN:Q<λ$_eQ#8$iTyݕ"t|ys,޹A?m (yO%OOٓZՉjfY .#9H,taǏM=aѯ:Z]\u^^+7oyNrte~hڵQ6v6~~ڇDFihvǎ+֥Qc.QSwwjo*Awd9rN#9wEߪ5kҴ>똳k;Hl!L=h%p޺{W\/s!;{l'ݺu$QKVZ.^w8u+7Udڕ[s   @a 9ϬXԭGZ,>~[e?oGz5#?J8pu3O{?P%S5YdF]F3HN2-ӧ-ZЏڛe7=׶DObw4dté'Ws׬ncǪƏ ADusϟ?FAӦM5k֨h^mSZN id$fr@@@ u@@ ȏA"gq΂B"ݵ \J9-?lJZ<U&<:/))($lϼԾA k|Mu^{GGϜQnQS7wﯸZKҏSFwJ=z"gm^I=ϫ,Z>V)I1_uD.mmK7lP9:oNum[<qW"-]#>"?k}לԭfl뽶~էe~@.2%-:u`TTL⢤,{bnTcգGj߾=I|=J 7nPUӫu%*יiHvB'm@@@ @ _@@ LevtH}J?=&) ʷjERILDN !2ܼ6G񖯦S…Bzӵ+Iz/9٬wL,=cج>^lKH4\;tz7#g,ݯĶ_nJvGΜLiˆ=b@ bFrB-׷;WE~쯛0o"*jr*̍=^EҖͰaM)Qj "d樸㜋2G̙͌^ҥ=Cda5!y85z?ysL۶GNfK@1~gX޼*=?%6s:ϵc'vd#8S:r CyeqRSuӘt Z$W|4om\0T,-쀁@9  `r2y4o<7xVpdWIکK2\}Np={@pcГkqRU>)[Uf:W5'Ojv%WQD;~ߺ{;JWoޢ׋UCs.K3;j\<t#RtJ,ɢυKLͺ*.6gw%{udͻw(qx`εm`^]KQ63qn:mӷ"yg[[S&O{}JdnQkbReNnr*3;׶[FOXp*ƍ{/Q۸hXbԻܺw7b'\Rيxȱ)SPүY/lUH2Iq"3~w*HrvG?>K[*]R\M}C۸o_ZK_-ȐӧHvq|\nZR8~#7sdȔݏԫG3V}R4ߏD,~reKD)RM  < E@J"5.$K .sx?{g/Etwwwww*Ht7ҝ%$%EAͲ<6f̼|ݙ;w=܅~Q8Z,6MjijNy3o?ũ%1GXw>}/t?#ẦMo 0NP*o>GRNc eP o̊D-[ѠVB<)FtMz=xZ(1ZȼT*:w*}޳cSIҏK92š-Z>OPL^!%sㄉjq|$=X͚5i?$! ^Iv9fH[ (@UE+F[lH&meN#(OH2vnI")8b};81i[xz  `lC~yկ_?_+!cwTzS5SGw"$pD9ʟyA%‰YM45m;*iZ=%R\}G.ܔ'vM1!ST{'GjW(Ok}M̧wP:2]L5h@}5W{>];Dme@C3G7 ~9\$mЖ<( QX "zl,{)V4No<ڠrlftjL$9B6EHN}˗y^ޗkor+&"jIR<0h6h'^D@@ P4Wo#Nsny^LnX0}BP$ErU6y\.$]~CBS Li^Ww[+,S~5eD۹ IT[PZ`Em0c8sɈ՘;c&BEhk+O&esym1YLpɔ/K:u"jyQ,l[#,>E itU_KDwԴ~w> _[Uܮt;o?̃z9U΍ou+VB[PʾfosVaae0+~-oFEt;F~KpIaČ~eA@@. ڥ'2^YW ~nQ1A}f}yomWP7z2mH/ ޛ/>> c_4yBGޠj/kB;A@#.\8J+4I)nʲ&i&3*1O/7zs3|`o֞vǎMQ#Gz߾\iҤ@@@ 4{ T^ݐK2TތEBe7ԴK*o9ҧn'F9< V(TDkS>媕(it:ƌޣ*eF7 zIc]i}}R!Vv;9sęo̭\(  @l@GO=/K?elEa„u*~V7wH6ٸ8ݕc1bPuqF+ "}Z3P6EK]e^fٲ5mZ]͌5*u@WYTk]F~p:gd F9 2}!;t@ $0Oh 4!8?%KFK,!dƥF-z Ic;wz޻rV)^[X1۴rV) hdj+os΀IĔ=)wL^BIjX+J򲑣(A8Ye d3"yVrǎ-}#b̾~6ϺCZ;jԫI,HFZ@@@ *4O?oNY8BוŔ*IW-[Æ,$D6VvϙK1E`7|ӯ}ݵIT}556]fz-bֆSˆXp0#V4W/ؽĉ̛6Z3yD=uۚ|.3U!eJu*9\Yth$vs+֗ʗ/\;*lq'LtU|y7I^;iVMej spx    @\l&Yz5߿?@=]v֭[+8j4V4eNZo,'+ocƇNϟH*.BP #:* .]ѓ'i:v,O-JqD>V;={4!zS76N_ެiR…Ir3[>}J_JׯsH7sfAyw=ӧ針;I=&֔.®&?M9By|T|ǛͻwT*I0yf?w._NΝSYh\ThJ/R+Gr iݚ>)^S/i73 vְr!]`94{4*_\~VlJNxΚ&-u[2*wШE(L0]ʗ% թ`{7~6MZWPeIZ~VrO\5'^p::|vR$JDs妶5k3߼yC~>x>yBS,Pڵ)I|ϟC?I~K{}9ujVD UO+"/$LĆN?~g:Rz>}?;zE9k>G  `k_f͚qs"EzLH-#9~=|YC3Wfc? C)RĈ^O9`t?0処f9C~ĉCY Ν)˴Fv3ijם\16#~} YR4!gً^}ڼw׏l?mG=7vezŃ4,6/>5`^ѣxFhd.>yogĥKﴩ$9[{/[519{:rAR42=JrUb%I? ]<{F]vW)VM(*[+*Lե3Ze#)Jtlꧾ} LQ߿psո+y8ۤD+߮Y):Gb¡JѢz5SOnʴF?qG_B jy6PD4a#L-m5ywŋGXЕ4;brO+_kV'B~33޾vA88 V#(ǎ{{!-)\cwei7y2evK^*kYi{̦;,J=G9%:^$o׎pٕo }C۷wex7ɓ'IrZjQUto* ٮ~qO@@B5C58  `O>nݺQ"Eԏ"Iː&Mр2LCu>Ijꇳly3HӦGp(uҤ^%=ʍQ#Gfի[X4-AEAW]5="2mv ߇8/4C$ZD[UnxRwc%h+Lߞ|\2A1s"5I| bO'Qf2_ےVKG1w~܅bst;whޏ?M{4XgqWk`Hi8bSe_nU8]ؘѢӴ^݇qv!6mڤv5mgqW+/QÇW/o k_h@@ tރ L0OYdTxq> (*Owo ,Df&dE/\HsDunԡN|P&[cC~o͛i馍\<ѧݦ{r}ymEəA7 *͋K" hђ~m~R@:$"o҆(n\=[_sG%*6_Ds:% &B5a8yp O|}oKZ1+џL兲gWU`&AXlYݞ_BLU^h+8ľ_~}}ἶjnD^l (IYx}ՇGM)Bw{0=@_Rǎ)2GY"i eA1LRGwϮ oϭ[L2| B"nwdt y0&Grz2Hr}G  @LO@rI苉$Qq?˻ws(ƹ4e*k`DAO[V1wQu>_  D&Y*.BM슋~k ImZ&jjw$D֭XiC|DaWW3vq~兌bGA"v7)%TUoO藛5]ͥ9ahߑ#oնB\Ҹ /ʜ=mIY^y>mQX̓lܨV̓K9Wg/^Щ{M65?sfWSݺ^Z݁ߵʖoLSHrW#I[@ONEʔ2mۨW/8?m)B<'G*j&iY\]ʈ#n:ui4%Α9ouYl:.Zr搇GO~;8/-X{L؜))ܹocVlJM &TOʹN}1eH.ݸNkwR3>֕z5n9˱"ɽ>z_zzEc[ T-ڰzO"-j?o]g_Dݧ~ AMrgA'|ʀĢ(/Eʽ̓/X,*/$%MHv&E6Wvg4lP{ߢE(I$~Ml}烂 7OwII%lE"Ph/Y^ypPqNizS&tmNVqtlP1DL%ױs鮯$Ϭf"nڅ‡ mRYXթ5zӦMTpar}Gw&, $HDpuuP?783ZeK+nKXD4ϋeHRU9aɒ:ټwM]"sD9!(XDo-MZݒ%Hp3^T˿Q;xn'_[ G' iG'pDk{!`8[sO=_fAײj0RoݻG)m1a)WEhf33/T\fͦ.]iDh=&V/\{m:!I`לrϜ9>~q71 8܈kKxb梑   `srtuuhS]C V`Ae*o{Ƒa9꾍Fvz5rdwEm]G8K[2wY$IK-J;K4XjDhCCʁ/Ed_fGWe?fUVtAWKGGyj//64?ϒ'LD8?)˗&Mvy/YRnȓTv3!rʢxs pNŹ"vC eϮ=y׹K{w%b`2=]Ζ6]rG?9kWg @2xW\9GD˗A$ it]jsOrL$%ZU맼Z//@^@4JȦpQ"o;垕DغcdLc7jDMv6_i,jr2Ke7ߨZǎoncÃ8B  Ao`PD   pE89{MX?O& 2Jv N%[$Z\R%IU Ωb=1>ydAq$׿>Er*#C0cM9_gY1|p%*Wr|cma?o̊D-[Q  !RZ?q.ݸƓE졮kEɕ1#I~)Gi;> 6I%2u# 8^,N=PHJqm)9Gt#}CJ7MՋjM7ܡRk f˦Г=z2 f.^Tْw89/(7o`*ݦ5|6kʋ%R &, -wz ]ځqJ7l3^1dj:xz_F_~i%%'܆HիiKd5آ\fd }K7o2w.](GJ A`m8N  `xmӕp@B/'NPΝindAN(BIT۴lKR߭Gq>2Ͽ߱OH\y ƥ,{bwiȬYJr)=.ɲ-?,A["DѮeE6g6MX!Vk3~TLb܍~c(3:.Kɭ 4N=puzݹ]\݊)|ذ-=yB2A3YdP<*J>NүU ֫XN_L9'E~˟X)i@bAĝȵkl $" sqr wgYtbLS LiE֢U#c;$V[ըA3X&;3UM/L5<ȱ`U`pT 3fRѮʇ'qY'Tc"R+~.9,E( %{L⏫&$_qgǠӦQ,YNE|0HIibO/.lM2=d@+V0mɑ9; yfƥ7.Yr5+C|1.W1RV뙾;G*ײP_ѕ7(GJ~ВbZ|" ͺ̜AX?6l2V) >XlH'=1/*`:% FoƉ@@ tW~˴[<כcNVejކ HYh" dVxuǾ) $8s]l>4_ܫ,2Gl{9<c%[(jkm\Ey`&)8֪E pj{ {5~?,{*Uh! * NW"Ku'hXvԯyr;xB͆ uΕs?mGk^O f xþfmUƏK(?K;^j}3S+~ɴ~`LDuWB3)fBrD]FWxaJC,,!]gtzcEݧqY9[e:{mֿIܶP-o`*,h`rid<R,=a{ӱ@f1zCKo{x & iNqF#&9nCFW`}O^5/>#i^ܵV7~r}Q?NzOlF\΃t/筫䪎v{EH,  %r  'mQ'+8aX3m ~{j/\cmvۨ6xk̨V6v_;   `gxܻ @lL@VϘ1!eu[D(RܰS4Δ*cv/>|~2ԤXx cF߫\;0Ԧ1c1ׇll/>"0K^R(  `:xq#V\9#MY6RĈTD m 6,}Zf-(@u7/A8T"OnZl+zt+=;%KPwyQ ^t ׺=hy1GrvYϤ˔]Y ƏJͫyѢD .oւs䠤 n `c`   ozkD9&]vDѪ>)^Σ iӚx#jgz Uiݩ3hמ‡ Y Fny"ꨟJCPdɩuu=j4eK]e^b"T&~]L0uSGWYN,fə, k֜$\5VI|վ=93E -}@ձbcƌq<CJ(  `JbŢkRld8fXjL^<|EYXq١|Xt쩈שn=j^Y@Ǻuŧyl{e{ bu x[:E&XJ;jW!/~0Dܶ̄'P8q=>E Z1z)+ ѹrX)Vϝ屌vʞf5JSF_X5mmP lc9gOƂ> @@kʂ@8ǐְ!2w.ŎtmHd 9sI*ѮkǏpmcI_7~$hn'v>oտ??elѦ)S}m{Dsj}ۍа\F94=SbŴCl(S_G˖S lD_u*T@ 65ko { v-,H/p9! lE[Ϡ^D`A q}\y;̲ATI| `|?k]`?6'acT@@@FիW}9ܧc\B?=:FB({Dyr%:|$=}R&NLsd7wRT*B:Eϝ7SP,Y-ɓ'3-QX0ߏM/]>GYӤiǩO>%W?$W^|ȕ@(4Q%ݻ?c4r S",& h_G*"5:M_i2B{_Ǐӣ'O)yT$GNగ/_Çթ쐘1ci9>~izJQ kV~,pA e;Ib ßv{s"&3"Ec  +WX:@@ T|*UX aw%_6E׌,f>DZ`A"YK˧mʉ]1⁡Ŋmh1I0I(1_h̩S&3?~_FeG׭  3h " "/5\T  "^ o@@@@@@B"]z~@xQ9Dá  :@  /A@@@@@J"U{`!7X0$       y @w;k   *NT      AH"oE  `Mxoh5@h%7< Ă       `byM9h/g!7p88@4@@@@@@ ;[xq% @r  `x@Ӄ@rqf<y%j kBSA@@@@@@#`'ؑ^;*| ޾ Pp@@@@@@ ں{8LA@@@@@@. ڥ'x$# kCA@@8XD^kZ  : @ @@@@@@@ ZpF7B      v @@x?@       `Symڱp @ 4{>yC_c[ks       D^P @I5 0~8@LBI:`'7ؑ   6Q      V"J ~@@@@@@@ :؉@8;9_@@@@ܺ{jjMi' ʛ7oh?χS/'O(}%uj_6%ߖ?w._NΝSYh\ThJϞ>W_=zЕ[hHIYz_vCPReʑ>rV*p5Zu+=|k>N3CF\eLJxlU~',Yⱌd:*l+nBr{eNZ‡ oi5^|]~>q_F)%rSۚ5)nXT*I]Iv8@s֬S0auP4gNti 6l/"/%L:i4g*_n޼IJT|۰acQ@B+7ؔׯ+8u"E٦^qj4`$n޻G>|GМkhxvԳqY__/^d_|m޻ޭӧ7mۿ=GNlVҲ#){&.]J}M/_:\9q>$͆طH#ztCӢ+w1RlYZ2|EA""nl2dϞ=3DŬY3:~8Eб(  @lF%Pر#mWy;=ݻ)2BO(FԨ穓4e^LnjረT=";g^M#U0*D_6lH&hȬYשSTu+yRmLΑ} Ywgqctrۗ}ID\3R-|U"Q=e2eIQQ&Gx޺wO˖6jp%JfZ^J5rdں77jO"-Vmc:c rxU"Y„4eKʗ9L}Zz򑣨frj2^QAiGf^';fիS )bϻ ȪmӧqT="?VFf?h=( @lH~MK$LbnL ?7j9tuf O8Uu'9| \%2lH ?/P oPM6J"$J]ݴɒѮYu4ivŊOt[R =G^] :a#O-WNzvQmϙ!{{6K֯ys~>vA881s9EADZc^bDf9w;zqc\ K48ϝ{2PT:_~ }b@}Ӹqޛe}=GeqXd83  `"O9[nTH%F))8ϝmӞ=ʽU'j>GD,tԎ7㣤"x?FwA%M"ĶDF+_Dm;+>n>'b^xY>jE|g)ޒ_[L"֯pJ䚮ݻ7/9}v~oG}r+T|sv0ŋM!jIߎ܅bswмvYgԍ#Ȁ3FR'M9:_xd0 3^hQUϴZ_#=/=Z}f=N]Iː`  @5 A@LF`„ $(sj1Br,S4 d{UYӼ,yyn2%ݨC:Xѣ+7%oǏ/ۼnȋţ},cOP$b_CycM\Nu6lDqڥ1bH!fohNw=~67Tu~V-5ɝUc瑈E|V˽Pʯ,U/K/\Hsꃖ EHW*E-m;)udbkD/p#`FPO@~D%HKjQ8?-~ts6~LRhFGV֬"v6>tH=|qlUOzANyg5x+4u$/c)ۚeaXBhQL &G/\mIU*7ܮ3OΜA_`(~jobcbRRi[+gD>%HGD=/#mk֢v6-EDVYd,1 a)'/ԉxX|J|$&;c&|#/V}bFFZ]-h%|mkg]ctgH.P3Η4Xfj6T)i)kZ?4,FԷtqw.5 `8~7-˗xb=,/6 f]y%6OW"wymA@ @o(x   `?"Vԑ<{FѣF%G8~ [l&KNWoEgvҟK.]UDHZY`_s*+7]~FuH*Ur"ej,Tg%t;V(c'rI:uwt{\ʖNTVj~-e]i!yL%=GTkW},G"wki(d>sYDO[z0 3?{J}4U gׂu?Rgأ'o#[#EFz_u-xO͛w8'."y 8;}@@@JjI()SfY4\6ԙZըA[.kdZ+`='ORۯYsk4:ZY|b !!A6̕+/$Y&f`5v3?0&wb{Bl’%Qmֱy|Z}aHlڊ?wJ`W%KqJ;^;?Qsgdo,?7^qz)nR]LR7"ܶͱO$DK4`-T1[m3f:R -fe==iݲ;{~Z6 ]a;+hV8g`T~4o2R$Jx'PM"/XPH5Y:_u}/e%Ob0j 1پF]qݱ9]V|4;ݺ }mQ1b-gZTQUGNqYtgDrű𚻲V.s93dQ۴E>(` Ŭ ڜpgg\bqbxq t3!ʢbs p;ۂ}SW\|yÕ0(&Y2ˋ<]ٝ=ywvlܘ**MVK+nUl6=oG*W%0AE͝)-WUxA-'2;E<*kmyX5; ÞgOα{_RHH˖1e\FOYj&Mvy/?"\xC_c;? Fjբ<y*W^4rH*7=[{yIS/_N{Q8q˩z2-[hG5 $T\a|YU/m7<&uAZGcPt#nCWIN%Çs*fv]ᨨuޗkͿo|ƈVpkތ:Tk3LIk6ʉȵ|(gX\s>|?i;>3{7n7ǜpr&JGY?zߓ+/ߑDn&XA‹$v1Ew/|+ڬ)$I-s-/x ]w֍"ʽ\R^DoI )~^q%n$q$/ $M|+VYĒ@ P^:E{> @@ `  'Oq79O:u*EM1M̫KϞ=[X+ӧ:D8Vz.Jt6,{bŊ9lC\64w >>?tUvw|*s'l#Y"?(9yo8ӿm⁙f^^K/P- ݼ{#"8ЧIʔ*{ۭ"+&XHԱY$R'-윭p|/hʃqbƠQz5}>YiTZ$}V}y&dt ɽ\v$7Jλ,\3gNL׮M9╅E5\$zfu<3*8z]-Z"rM<fth鷖wS%I|KIKxق >woNڢE 8g:僁#W'! _z%uX?hLo+^.Qz/,Vs=Cʕ+ɂnyŋԘKnJO&BQ,z)3UEa{j8l9bs|O֯Ƃ]LÇ -ݴk9h⭖S0~)v0{<{%ҳeS`wX׷Kٿf^9clG).\F_8_ʛ}i/~;zzp:)ؘ h/#베%FS'M8x=Ф$o_֐paÆT[awx3B 1E*JZue)RP%ԎLR!6lXYrdJs=vN3mCg]V`@D t$zm/&S|n_xe7˚,:G6Gafo9^W?{JylҲoy#y[ x ϝ6*Or$;ؐYS ; dȌIáԵ9V3/z=o7n8 @=<9ݙZ/ZP;:sD:oܸAG<U|k֬1tjr.7cV;ym#E.uy=DիW^˅D?92_szM۵-C$R3Y=0a(ZQ<t-~ Y?B1zz*+~ڷnq4k5۶jڝ;Ӧ1ca΍ZLȌ u&o/xU[R4io3\~T$snYo4_J)o~Sl4,[I,ȚU!,'׬_պ7(L X @H{>؆`+3mjux=)zͫ^Ou8s{ya0z9èszD|'[=xʝ_ZtFwwMۙ4wt?fSJ|zG/AeR ^xvΈ]6Ra{;ׇ{9J]kFeo޻yzWTGsfzqOD0i#Fd"#ί"կp~ŨETMV;Fݦ`ìRYD w$@@k`#7n\u~i< iox8}sm:iӦi|𸕧iYT *˖-:})y h GI! DH}2X`V 4@6\Ϟ=sL JnȤH[\ոIOQTŋ,fOus~k1+tZtiڡ3WgdɒA&9GXTʗ/oHR %!WD -˓[NݻCDv  o̾I&4c ʹ=M6"Jyo9[9ݰ`F諯Uܟׯd8%GiPqzWNV &}-?]PHi{j RʠQΑDΒ%.gQΝպzZvm5/ej8@*a*=vJZ1V"7X>M[ۻ(㿄ЂQ!$ؠXB}Cb*bO j ET[J롧R+r"RkSQ@!"`P ?nfg'<{q;wl7u.|ֽ+ь:_ڏ6>i$IJm;O=h7gu YhgqICW+H% t՚pUt]5SH<`M;;h ъn T||\qP#~x #~i<]y׻&O쪙::}ĉR @& h^9w@رö]֭3nGzh0Dӆ k|ҶmbO}6lhiӦ9UUCw /FUߜ?ώ?utN#tꫯ.?{DZ9zԇ=Z+PGױza_7;VI;w\رc{%/c?t;o:6[G,?裎uTwXvKHcQ~S[z)**2Ӌ/fJxtSஞӂré! .Y֋@@6z[&66߿_>CڹIVkҥ&p̢ELV.]| %pBE^^^Tך5k&cǎ5& F-:j{ٲe&#ucqqq]d=?撿ʇE&D/j͚5KvkN?njYx9#=𾰰ۧO}voFyEa ZQz1#v>}=] z,~'!^ Te, n͛7СCHgMIsK,13fD5Ef4D=z!CZ`(9%IgּӧOO*p UҹV\iQ:3 ѣvVOQ5I:-GII .kںuTTT@X>d/z ނh$:jvtDtnb3^䜟n,tp} WGͺ\G3?u?Om=uM_@uy^Hvu}8[t.;/U^^&;&բޥ[ӈ|m~R/9xXA۶m3^[&y[l1>t[c]m u&ouFɆ@\r%һwoy뭷I;w4?ƌSms̑7^#t4ѿٛ    }D @s+x[v@ѥKo|A^To۞5:nB@@@H޴r@ z۪֭]Vm\F@@@@ "     A|6    $#@7=E@@@@2(@7l@@@@HF 'Y@'2ԩS:ujYYYUy,`adZ^g, W /gRLpq~oaYjin2 /gLgGnݺE6 @`fW@[ݻwi;&ׯ7lР\zu}?oBr'ݻW\i޼%]M؟|ش[3=H  Mސ5     `@F(      Y     ag     @x7d      @Fr2U6 K/RVX!$;O.riݺdee\CjlٲE;&]vרQ ѣGeժUk.)++\Ϳ ]VN8wQ=ڷo` |s]vqNUqNFڌuɑ#G\_swMJױfޓB9S::vB@'Y*OJ3@B&0go~#|L2qD7(;vlܸ1n ]F!L>]4:9r}ٱEq?:tH\ 4[TTX v??X^lܹҬY3N '#x}h6 tb6m{wȕW^)w6e˖ѣgz깢 .m6袋dfܿoy7䡇'xBjWR0>#?~G@?p =H) cg@xi? @:a̙g馛zYPP Ç5kֈ"A97_7]A#N;4nٲM/u:SL1[oU~UK.wɆ dQaUE7V D/L4ɦYa_WҶmۤ8%؅9Ǐxj^\;uQ*zJ`…2c ыRO^#~!k~c?Oٿq}/sx&Oo tܵ̈'~z+׀ ۷O>KU965o\cudBc׭X8ꕔnժUҝ朖4aV7%\"FrT7LEO< zaJ={LخT0a'LvE `teuwW+`NIoM:wxb>T믿ۯ_?93m{٤I׶. j%`:E۩eec_9Ŋ9>Q/fgg˘1cl[G*x ߻zajq966T/t O;f#Aشi^Qno TTTȎ;cǎt䮎KֶonWL^tGN`EGܤ'NcR2::^h撮l:d-]\xsuuG8b:u~`حv  ].z#G86,'kw{a|F @7{> FK6n8ntJ6DZ5ӮO-O^V^-:J\S=\uP| 7 9r9rAӟTXA2=ϟ/:jd֭yc'GD:^A zTVNv*mJZg @? ޢ @H>lz|$"k}n:Vi}R#<-"W\q[} ^O^z--vo~H) nL@;v*!dTzZyyyvhL>#Qr>k[n֗h{S`ٲeČ`̙3S>VGq }@ KzXݻC|Wiv* |fj0`@lq>MFYgq~rΚ|/, C`$X@ =ȟyԩQ+냩* /1ʢʬsέѫSL1wIڷo+S$ c>}:]GÇGA;t4,}pۯkS_Zje \tE}ɓ'G]:u̞=[VZ%ח(58Ej>V?7kosZ2nlڞj0<|3 xQ`Ȑ!vZ)..[˗/7_}`LΝ駟?ou&7*ק[z-5j 7ǩܹscƌϛ -tդ'v= K/TUXӑ ꫯ/ֈt=n^._@GO4L*u5kȦM̜?X"[*s̑7zae * K+MKdYiֺy @mOw*Xᓧ fa8(**'ǶmLkֿ]wU֏7{Vi+eD%WkTo}[\@)45iDnf+Xݽ6mȬY̔  t~p=&}IVp---5^YA@:ڶ#S:G"*o ;5@ȜE:\`F%ӷk.r&:EV@3zWGeh¶)?t i׮q]BpΕ;CE@x=sh     $C֜t(C@@@@<,@;!    Nxt(C@@@@<,@;!    Nxt(C@@@@<,@;!    Nxt(C@@@@<,@;!    Nxt(C@@@@<,@;!    Nxt(C@@@@<,@;!    Nxt(C@@@@<,@;!    Nxt(C@@@@<,@;!    Nxt(C@@@@<,@;! C'ۛv[Nϛ7ޭ*qR  S)]  xSСCҹsgMdСQݳgtAJKKArJ9@@B'r:  5Fٳ%''4mѲ{fꘌf>wtx [o?G@@׮]e5eee2|i@wdĈUeA@S4{{@@ 蜺l2ӪW^y̹{UWɱcǤUVfiڴZMS@@2)@7l@@۷KNҲeK9efw}Wc#  @!{# xN //OOnڵw^&L 빽E@@ 07   PM_~pB߾}{ٰadg3>  @# xODVZUհM6Iqqqg   ` $xE@@#o>ӚN;ͼ2DKf  xEW@@@R^ ;SfΜi2l0@@`(>   9͛7˕W^)-[yw6m*СC3H  )4@@ Ǐwϟ/7t.r9eҮ]Ro@@h-  0aBUpwРAU]m/O=i宻'Ndl@@CΠ)  XtS***Efj: 7 oGGV @@p    8ptQvaZ6o= 0", "y >= 0") ) latte_max( "-2 x + 3 y", c("x + y <= 10", "x >= 0", "y >= 0"), quiet = FALSE ) df <- expand.grid("x" = 0:10, "y" = 0:10) df <- subset(df, x + y <= 10L) df$objective <- with(df, -2*x + 3*y) library("ggplot2") ggplot(df, aes(x, y, size = objective)) + geom_point() latte_min( "-2 x + 3 y", c("x + y <= 10", "x >= 0", "y >= 0"), method = "cones" ) latte_min("-2 x - 3 y - 4 z", c( "3 x + 2 y + z <= 10", "2 x + 5 y + 3 z <= 15", "x >= 0", "y >= 0", "z >= 0" ), "cones", quiet = FALSE) } } latte/man/print.tableau.Rd0000644000176200001440000000064013104624164015176 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/tableau.R \name{print.tableau} \alias{print.tableau} \title{Pretty printing of tableau output.} \usage{ \method{print}{tableau}(x, ...) } \arguments{ \item{x}{an object of class tableau} \item{...}{...} } \value{ Invisible string of the printed object. } \description{ Pretty printing of tableau output. } \examples{ # see ?tableau } latte/man/tableau.Rd0000644000176200001440000000144113436637052014053 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/tableau.R \name{tableau} \alias{tableau} \title{Tableau Notation for Markov} \usage{ tableau(move, dim) } \arguments{ \item{move}{a markov move matrix, where the columns are moves in vector form (e.g. the output of markov)} \item{dim}{the dimensions of the table form of the move, oftentimes a vector of the number of levels of each variable in order} } \value{ an object of class tableau } \description{ Print the tableau notation for a Markov move. See the reference provided, p. 13. } \examples{ vec <- matrix(c(1, -1, -1, 1), nrow = 4) varlvls <- c(2, 2) tableau(vec, varlvls) } \references{ Drton, M., B. Sturmfels, and S. Sullivant (2009). \emph{Lectures on Algebraic Statistics}, Basel: Birkhauser Verlag AG. } latte/man/pathing.Rd0000644000176200001440000000437014774757515014111 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/set-paths.R \name{pathing} \alias{pathing} \alias{set_latte_path} \alias{set_4ti2_path} \alias{get_4ti2_path} \alias{get_latte_path} \alias{has_4ti2} \alias{has_latte} \alias{missing_4ti2_stop} \alias{missing_latte_stop} \title{Set paths to LattE and 4ti2 executables} \usage{ set_latte_path(path) set_4ti2_path(path) get_4ti2_path() get_latte_path() has_4ti2() has_latte() missing_4ti2_stop() missing_latte_stop() } \arguments{ \item{path}{A character string, the path to a 4ti2 function (e.g. \code{markov}) for setting 4ti2's path or a LattE function (e.g. \code{count}) for LattE's path} } \value{ A logical(1) or character(1) containing the path. } \description{ These are helper functions that deal with pathing to external programs and asking if they are present. When latte is loaded it attempts to find LattE and 4ti2 executables by looking for environment variables specifying them, i.e. their paths as specified in your \code{.Renviron} file. } \details{ For easiest use, you'll want to specify the paths of LattE and 4ti2 executables in your \verb{~/.Renviron} file. They should look something like \verb{LATTE=/Applications/latte/bin} \verb{FOURTITWO=/Applications/latte/bin} You can set these permanently with \code{\link[usethis:edit]{usethis::edit_r_environ()}}. You can change these for the current session using, e.g., \code{\link[=set_latte_path]{set_latte_path()}}, which accepts a character string or, if missing, uses \code{\link[=file.choose]{file.choose()}} to let you interactively; you just select an arbitrary executable. } \examples{ has_4ti2() if (has_4ti2()) get_4ti2_path() has_latte() if (has_4ti2()) get_latte_path() # you can set these paths permanently with the following. note that you'll # need to re-start the R session afterwards or simply pass the path into, # e.g., set_latte_path(). see below for more details on that. if (interactive()) edit_r_environ() # you can change these in your current session with set_latte_path() and if (had_latte <- has_latte()) old_latte_path <- get_latte_path() set_latte_path("/path/to/latte") get_latte_path() if (had_latte) set_latte_path(old_latte_path) get_latte_path() } \author{ David Kahle \email{david@kahle.io} } latte/man/genmodel.Rd0000644000176200001440000000225513577325403014234 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/genmodel.R \name{genmodel} \alias{genmodel} \title{Generate a configuration matrix} \usage{ genmodel(varlvls, facets, dir = tempdir(), quiet = TRUE, shell = FALSE, ...) } \arguments{ \item{varlvls}{a vector containing the number of levels of each variable} \item{facets}{the facets generating the hierarchical model, a list of vectors of variable indices} \item{dir}{Directory to place the files in, without an ending /} \item{quiet}{If FALSE, messages the 4ti2 output} \item{shell}{Messages the shell code used to do the computation} \item{...}{Additional arguments to pass to the function} } \value{ The configuration matrix of the model provided } \description{ genmodel runs 4ti2's genmodel program to compute the configuration matrix A corresponding to graphical statistical models given by a simplicial complex and levels on the nodes. } \examples{ if (has_4ti2()) { varlvls <- rep(2, 2) facets <- list(1, 2) genmodel(varlvls, facets) genmodel(varlvls, facets, quiet = FALSE) varlvls <- rep(3, 3) facets <- list(1:2, 2:3, c(3,1)) genmodel(varlvls, facets) # compare this to algstat's hmat function } } latte/man/tab2vec.Rd0000644000176200001440000000134714263604125013763 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/tab2vec.R \name{tab2vec} \alias{tab2vec} \title{Array to vector conversion} \usage{ tab2vec(tab) } \arguments{ \item{tab}{An array of counts} } \value{ a Named integer vector. The names correspond to the cell indices in the table. } \description{ Convert an array into a vector. } \details{ This function converts an array (or a multi-way contingency table) into a vector, using a consistent ordering of the cells. The ordering of the cells is lexicographical and cannot be specified by the user. } \examples{ a <- array(1:6, c(1,2,3)) tab2vec(a) data(Titanic) tab2vec(Titanic) Titanic[1,1,1,1] Titanic[1,1,1,2] } \seealso{ \code{\link[=vec2tab]{vec2tab()}} } latte/man/zsolve.Rd0000644000176200001440000000261513577325403013764 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/zsolve.R \name{zsolve} \alias{zsolve} \title{Solve a linear system over the integers} \usage{ zsolve( mat, rel, rhs, sign, lat, lb, ub, dir = tempdir(), quiet = TRUE, shell = FALSE, ... ) } \arguments{ \item{mat}{The A matrix (see the 4ti2 documentation or examples)} \item{rel}{A vector of "<" or ">" relations} \item{rhs}{The right hand side b} \item{sign}{The signs of the individual} \item{lat}{A lattice basis (instead of a matrix)} \item{lb}{Lower bounds on columns} \item{ub}{Upper bounds on columns} \item{dir}{Directory to place the files in, without an ending /} \item{quiet}{If FALSE, messages the 4ti2 output} \item{shell}{Messages the shell code used to do the computation} \item{...}{Additional arguments to pass to the function} } \value{ The configuration matrix of the model provided } \description{ zsolve runs 4ti2's zsolve program to compute the configuration matrix A corresponding to graphical statistical models given by a simplicial complex and levels on the nodes. } \examples{ if (has_4ti2()) { mat <- rbind( c( 1, -1), c(-3, 1), c( 1, 1) ) rel <- c("<", "<", ">") rhs <- c(2, 1, 1) sign <- c(0, 1) zsolve(mat, rel, rhs, sign) zsolve(mat, rel, rhs, sign, quiet = FALSE) zsolve(mat, rel, rhs, sign, shell = TRUE) zsolve(mat, rel, rhs, sign, p = "gmp", quiet = FALSE) } } latte/man/reexports.Rd0000644000176200001440000000064314263601516014467 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/set-paths.R \docType{import} \name{reexports} \alias{reexports} \alias{edit_r_environ} \title{Objects exported from other packages} \keyword{internal} \description{ These objects are imported from other packages. Follow the links below to see their documentation. \describe{ \item{usethis}{\code{\link[usethis:edit]{edit_r_environ}}} }} latte/man/vec2tab.Rd0000644000176200001440000000216014774757574014005 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/vec2tab.R \name{vec2tab} \alias{vec2tab} \title{Vector to array conversion} \usage{ vec2tab(vec, dim) } \arguments{ \item{vec}{A vector} \item{dim}{The desired array dimensions, oftentimes a vector of the number of levels of each variable in order} } \value{ An array } \description{ Convert a vector into an array given a set of dimensions; it therefore simply wraps \code{\link[base:aperm]{base::aperm()}} and \code{\link[base:array]{base::array()}}. } \details{ This function converts an array (or a multi-way contingency table) into a vector, using a consistent ordering of the cells. The ordering of the cells is lexicographic and cannot be specified by the user. } \examples{ data(Titanic) str( Titanic ) str( tab2vec(Titanic) ) # convert it back into a table (names are removed) vec2tab( tab2vec(Titanic), dim(Titanic) ) # check that they are the same all( vec2tab(tab2vec(Titanic), dim(Titanic)) == Titanic ) } \seealso{ \code{\link[=tab2vec]{tab2vec()}}, \code{\link[base:aperm]{base::aperm()}}, \code{\link[base:array]{base::array()}} } latte/man/latte-count.Rd0000644000176200001440000000630713452525567014710 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/latte-count.R \name{latte-count} \alias{latte-count} \alias{count_core} \alias{latte_count} \alias{latte_fcount} \title{Count integer points in a polytope} \usage{ count_core(spec, dir = tempdir(), quiet = TRUE, mpoly = TRUE, ...) latte_count(spec, dir = tempdir(), quiet = TRUE, mpoly = TRUE, ...) latte_fcount(spec, dir = tempdir(), quiet = TRUE, mpoly = TRUE, ...) } \arguments{ \item{spec}{Specification, see details and examples} \item{dir}{Directory to place the files in, without an ending /} \item{quiet}{Show latte output?} \item{mpoly}{When opts = "--ehrhart-polynomial", return the mpoly version of it} \item{...}{Additional arguments to pass to the function, see count --help at the command line to see examples. Note that dashes - should be specified with underscores _} } \value{ The count. If the count is a number has less than 10 digits, an integer is returned. If the number has 10 or more digits, an integer in a character string is returned. You may want to use the gmp package's as.bigz to parse it. } \description{ \code{latte_count} uses LattE's count function to count the (integer) lattice points in a polytope and compute Ehrhart polynomials. } \details{ The specification should be one of the following: (1) a character string or strings containing an inequality in the mpoly expression format (see examples), (2) a list of vertices, (3) a list of A and b for the equation Ax <= b (see examples), or (4) raw code for LattE's count program. If a character vector is supplied, (1) and (4) are distinguished by the number of strings. Behind the scenes, count works by writing a latte file and running count on it. If a specification other than a length one character is given to it (which is considered to be the code), count attempts to convert it into LattE code and then run count on it. } \examples{ if (has_latte()) { spec <- c("x + y <= 10", "x >= 1", "y >= 1") latte_count(spec) # 45 latte_count(spec, quiet = FALSE) # 45 latte_count(spec, dilation = 10) # 3321 latte_count(spec, homog = TRUE) # 45 # by default, the output from LattE is in list.files(tempdir()) list.files(tempdir(), recursive = TRUE) # ehrhart polynomials latte_count(spec, ehrhart_polynomial = TRUE) latte_count(spec, ehrhart_polynomial = TRUE, mpoly = FALSE) # ehrhart series (raw since mpoly can't handle rational functions) latte_count(spec, ehrhart_series = TRUE) # simplified ehrhart series - not yet implemented #latte_count(spec, simplified_ehrhart_polynomial = TRUE) # first terms of the ehrhart series latte_count(spec, ehrhart_taylor = 1) # latte_count(spec, ehrhart_taylor = 2) # latte_count(spec, ehrhart_taylor = 3) # latte_count(spec, ehrhart_taylor = 4) # multivariate generating function latte_count(spec, multivariate_generating_function = TRUE) # by vertices spec <- list(c(1,1), c(10,1), c(1,10), c(10,10)) latte_count(spec) latte_count(spec, vrep = TRUE) code <- " 5 3 1 -1 0 1 0 -1 1 -1 -1 0 1 0 0 0 1 " latte_count(code) # for Ax <= b, see this example from the latte manual p.10 A <- matrix(c( 1, 0, 0, 1, 1, 1, -1, 0, 0, -1 ), nrow = 5, byrow = TRUE) b <- c(1, 1, 1, 0, 0) latte_count(list(A = A, b = b)) } } latte/man/latte-files.Rd0000644000176200001440000000273413442214165014646 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/latte-files.R \name{latte-files} \alias{latte-files} \alias{format_latte} \alias{write_latte} \alias{write.latte} \alias{read_latte} \alias{read.latte} \title{Format/read/write a matrix in latte's style} \usage{ format_latte(mat, file) write_latte(mat, file) write.latte(mat, file) read_latte(file, format = c("mat", "Ab")) read.latte(file, format = c("mat", "Ab")) } \arguments{ \item{mat}{A matrix} \item{file}{A filename} \item{format}{"mat" or "Ab"} } \value{ \itemize{ \item \code{\link[=format_latte]{format_latte()}} -- A character string of the matrix in latte format. \item \code{\link[=write_latte]{write_latte()}} -- An invisible character string of the formatted output. \item \code{\link[=read_latte]{read_latte()}} -- An integer matrix. } } \description{ \code{\link[=format_latte]{format_latte()}} formats a matrix in latte's style. \code{\link[=write_latte]{write_latte()}} writes a latte-formatted file to file. \code{\link[=read_latte]{read_latte()}} reads a latte-formatted file from disk. } \examples{ (mat <- matrix(sample(9), 3, 3)) format_latte(mat) cat(format_latte(mat)) (file <- file.path(tempdir(), "foo.hrep")) write_latte(mat, file) file.show(file) read_latte(file) read_latte(file, "Ab") attr(mat, "linearity") <- c(1, 3) attr(mat, "nonnegative") <- 2 mat format_latte(mat) cat(format_latte(mat)) write_latte(mat, file) file.show(file) read_latte(file) file.remove(file) } latte/man/latte.Rd0000644000176200001440000000060014774756520013553 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/latte-package.R \name{latte} \alias{latte} \alias{package-latte} \title{R Interface to LattE and 4ti2} \description{ Back-end connections to LattE (\url{https://www.math.ucdavis.edu/~latte/}) and 4ti2 (\url{http://www.4ti2.de/}) executables and front-end tools facilitating their use in the R ecosystem. } latte/man/call_latte.Rd0000644000176200001440000000155413577325403014547 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/call-latte.R \name{call_latte} \alias{call_latte} \title{Unified interface to calling LattE} \usage{ call_latte( which_exe, input_file, project_dir, opts = list(), stdout = "stdout", stderr = "stderr", shell = FALSE ) } \arguments{ \item{which_exe}{The name of LattE executable, e.g. \code{"count"}} \item{input_file}{The filename of file to be given to the executable, without a path} \item{project_dir}{The path associated with \code{input_file}.} \item{opts}{A named list of optional command line arguments to the executable.} \item{stdout, stderr}{Filenames to redirect standard output and standard error to.} \item{shell}{\code{logical(1)}; should the shell command be messaged to the user?} } \value{ \code{invisible()} } \description{ Unified interface to calling LattE } latte/man/plot-matrix.Rd0000644000176200001440000000127713442001070014703 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/plot-matrix.R \name{plot-matrix} \alias{plot-matrix} \alias{plot_matrix} \title{Plot a matrix} \usage{ plot_matrix(A) } \arguments{ \item{A}{A matrix} } \value{ a ggplot object } \description{ plot_matrix is a R variant of Matlab's \code{spy} function. } \examples{ # the no-three-way interaction configuration (A <- kprod(ones(1,3), diag(3), ones(3))) plot_matrix(A) if (has_4ti2()) { plot_matrix(markov(A)) (A <- genmodel(c(2L, 2L), list(1L, 2L))) plot_matrix(A) plot_matrix(markov(A)) (A <- genmodel(c(5L, 5L), list(1L, 2L))) plot_matrix(A) plot_matrix(markov(A)) } } \author{ David Kahle \email{david@kahle.io} } latte/man/qsolve.Rd0000644000176200001440000000222613577325403013751 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/qsolve.R \name{qsolve} \alias{qsolve} \title{Solve a linear system over the rationals} \usage{ qsolve(mat, rel, sign, dir = tempdir(), quiet = TRUE, shell = FALSE, ...) } \arguments{ \item{mat}{The A matrix (see the 4ti2 documentation or examples)} \item{rel}{A vector of "<" or ">" relations} \item{sign}{The signs of the individual} \item{dir}{Directory to place the files in, without an ending /} \item{quiet}{If FALSE, messages the 4ti2 output} \item{shell}{Messages the shell code used to do the computation} \item{...}{Additional arguments to pass to the function} } \value{ The configuration matrix of the model provided } \description{ qsolve runs 4ti2's qsolve program to compute the configuration matrix A corresponding to graphical statistical models given by a simplicial complex and levels on the nodes. } \examples{ if (has_4ti2()) { # x + y > 0 # x + y < 0 mat <- rbind( c( 1, 1), c( 1, 1) ) rel <- c(">", "<") sign <- c(0, 0) qsolve(mat, rel, sign, p = "arb") qsolve(mat, rel, sign, p = "arb", quiet = FALSE) qsolve(mat, rel, sign, p = "arb", shell = TRUE) } } latte/man/ones.Rd0000644000176200001440000000056313437126720013402 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ones.R \name{ones} \alias{ones} \title{Ones} \usage{ ones(...) } \arguments{ \item{...}{A sequence of dimensions separated by commas} } \value{ An integer array of ones } \description{ Make an array of ones } \examples{ ones(5) ones(5, 1) ones(1, 5) ones(2, 3) ones(2, 3, 2) str(ones(5)) } latte/man/ppi.Rd0000644000176200001440000000164413441334713013225 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ppi.R \name{ppi} \alias{ppi} \title{Compute the primitive partition identities} \usage{ ppi(N, dir = tempdir(), quiet = TRUE, shell = FALSE, ...) } \arguments{ \item{N}{A postive integer > 2} \item{dir}{Directory to place the files in, without an ending /} \item{quiet}{If FALSE, messages the 4ti2 output} \item{shell}{Messages the shell code used to do the computation} \item{...}{Additional arguments to pass to the function} } \value{ A matrix containing the basis as its columns (for easy addition to tables) } \description{ ppi runs 4ti2's ppi program to compute the primitive partition identities, that is, the Graver basis of 1:N. } \examples{ if (has_4ti2()) { ppi(3) t(ppi(3)) \%*\% 1:3 plot_matrix(ppi(3)) graver(t(1:3)) plot_matrix(graver(t(1:3))) ppi(5, quiet = FALSE, shell = TRUE) } } \seealso{ \code{\link[=graver]{graver()}} } latte/man/lattice-bases.Rd0000644000176200001440000001440213577325403015157 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/lattice-bases.R \name{lattice-bases} \alias{lattice-bases} \alias{basis} \alias{zbasis} \alias{markov} \alias{groebner} \alias{hilbert} \alias{graver} \alias{fzbasis} \alias{fmarkov} \alias{fgroebner} \alias{fhilbert} \alias{fgraver} \title{Compute a basis with 4ti2} \usage{ basis(exec, memoise = TRUE) zbasis( A, format = c("mat", "vec", "tab"), dim = NULL, all = FALSE, dir = tempdir(), quiet = TRUE, shell = FALSE, dbName = NULL, ... ) markov( A, format = c("mat", "vec", "tab"), dim = NULL, all = FALSE, dir = tempdir(), quiet = TRUE, shell = FALSE, dbName = NULL, ... ) groebner( A, format = c("mat", "vec", "tab"), dim = NULL, all = FALSE, dir = tempdir(), quiet = TRUE, shell = FALSE, dbName = NULL, ... ) hilbert( A, format = c("mat", "vec", "tab"), dim = NULL, all = FALSE, dir = tempdir(), quiet = TRUE, shell = FALSE, dbName = NULL, ... ) graver( A, format = c("mat", "vec", "tab"), dim = NULL, all = FALSE, dir = tempdir(), quiet = TRUE, shell = FALSE, dbName = NULL, ... ) fzbasis( A, format = c("mat", "vec", "tab"), dim = NULL, all = FALSE, dir = tempdir(), quiet = TRUE, shell = FALSE, dbName = NULL, ... ) fmarkov( A, format = c("mat", "vec", "tab"), dim = NULL, all = FALSE, dir = tempdir(), quiet = TRUE, shell = FALSE, dbName = NULL, ... ) fgroebner( A, format = c("mat", "vec", "tab"), dim = NULL, all = FALSE, dir = tempdir(), quiet = TRUE, shell = FALSE, dbName = NULL, ... ) fhilbert( A, format = c("mat", "vec", "tab"), dim = NULL, all = FALSE, dir = tempdir(), quiet = TRUE, shell = FALSE, dbName = NULL, ... ) fgraver( A, format = c("mat", "vec", "tab"), dim = NULL, all = FALSE, dir = tempdir(), quiet = TRUE, shell = FALSE, dbName = NULL, ... ) } \arguments{ \item{exec}{don't use this parameter} \item{memoise}{don't use this parameter} \item{A}{The configuration matrix} \item{format}{How the basis (moves) should be returned. if "mat", the moves are returned as the columns of a matrix.} \item{dim}{The dimension to be passed to \code{\link[=vec2tab]{vec2tab()}} if format = "tab" is used; a vector of the number of levels of each variable in order} \item{all}{If TRUE, all moves (+ and -) are given. if FALSE, only the + moves are given as returned by the executable.} \item{dir}{Directory to place the files in, without an ending /} \item{quiet}{If FALSE, messages the 4ti2 output} \item{shell}{Messages the shell code used to do the computation} \item{dbName}{The name of the model in the markov bases database, http://markov-bases.de, see examples} \item{...}{Additional arguments to pass to the function, e.g. \code{p = "arb"} specifies the flag \code{-parb}; not setting this issues a common warning} } \value{ a matrix containing the Markov basis as its columns (for easy addition to tables) } \description{ 4ti2 provides several executables that can be used to generate bases for a configuration matrix A. See the references for details. } \examples{ if (has_4ti2()) { # basic input and output for the 3x3 independence example (A <- rbind( kprod(diag(3), ones(1,3)), kprod(ones(1,3), diag(3)) )) markov(A, p = "arb") # you can get the output formatted in different ways: markov(A, p = "arb", all = TRUE) markov(A, p = "arb", "vec") markov(A, p = "arb", "tab", c(3, 3)) tableau(markov(A, p = "arb"), dim = c(3, 3)) # tableau notation # you can add options by listing them off # to see the options available to you by function, # go to http://www.4ti2.de markov(A, p = "arb") # the basis functions are automatically cached for future use. # (note that it doesn't persist across sessions.) A <- rbind( kprod( diag(4), ones(1,4), ones(1,4)), kprod(ones(1,4), diag(4), ones(1,4)), kprod(ones(1,4), ones(1,4), diag(4)) ) system.time(markov(A, p = "arb")) system.time(markov(A, p = "arb")) # the un-cashed versions begin with an "f" # (think: "forgetful" markov) system.time(fmarkov(A, p = "arb")) system.time(fmarkov(A, p = "arb")) # you can see the command line code by typing shell = TRUE # and the standard output wiht quiet = FALSE # we illustrate these with fmarkov because otherwise it's cached (A <- rbind( kprod(diag(2), ones(1,4)), kprod(ones(1,4), diag(2)) )) fmarkov(A, p = "arb", shell = TRUE) fmarkov(A, p = "arb", quiet = FALSE) # compare the bases for the 3x3x3 no-three-way interaction model A <- rbind( kprod( diag(3), diag(3), ones(1,3)), kprod( diag(3), ones(1,3), diag(3)), kprod(ones(1,3), diag(3), diag(3)) ) str( zbasis(A, p = "arb")) # 8 elements = ncol(A) - qr(A)$rank str( markov(A, p = "arb")) # 81 elements str(groebner(A, p = "arb")) # 110 elements str( graver(A)) # 795 elements # the other bases are also cached A <- rbind( kprod( diag(3), ones(1,3), ones(1,2)), kprod(ones(1,3), diag(3), ones(1,2)), kprod(ones(1,3), ones(1,3), diag(2)) ) system.time( graver(A)) system.time( graver(A)) system.time(fgraver(A)) system.time(fgraver(A)) # LAS ex 1.2.1, p.12 : 2x3 independence (A <- rbind( kprod(diag(2), ones(1,3)), kprod(ones(1,2), diag(3)) )) markov(A, p = "arb", "tab", c(3, 3)) # Prop 1.2.2 says that there should be 2*choose(2, 2)*choose(3,2) # = 6 # moves (up to +-1) markov(A, p = "arb", "tab", c(3, 3), TRUE) # LAS example 1.2.12, p.17 (no 3-way interaction) (A <- rbind( kprod( diag(2), diag(2), ones(1,2)), kprod( diag(2), ones(1,2), diag(2)), kprod(ones(1,2), diag(2), diag(2)) )) plot_matrix(A) markov(A, p = "arb") groebner(A, p = "arb") graver(A) tableau(markov(A, p = "arb"), dim = c(2,2,2)) # using the markov bases database, must be connected to internet # commented out for predictable and fast cran checks time # A <- markov(dbName = "ind3-3") # B <- markov(rbind( # kprod(diag(3), ones(1,3)), # kprod(ones(1,3), diag(3)) # ), p = "arb") # all(A == B) # possible issues # markov(diag(1, 10)) # zbasis(diag(1, 10), "vec") # groebner(diag(1, 10), "vec", all = TRUE) # graver(diag(1, 10), "vec", all = TRUE) # graver(diag(1, 4), "tab", all = TRUE, dim = c(2,2)) } } \references{ Drton, M., B. Sturmfels, and S. Sullivant (2009). \emph{Lectures on Algebraic Statistics}, Basel: Birkhauser Verlag AG. } latte/man/kprod.Rd0000644000176200001440000000161614774757004013567 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/kprod.R \name{kprod} \alias{kprod} \title{Iterated Kronecker product} \usage{ kprod(..., FUN = `*`) } \arguments{ \item{...}{A listing of matrices} \item{FUN}{A function to pass to \code{\link[base:kronecker]{base::kronecker()}}} } \value{ A matrix that is the kronecker product of the specified matrices (from left to right). } \description{ Compute the Kronecker product of several matrices. } \details{ If kronecker is the function that computes A x B, kprod computes A x B x C and so on; it's a wrapper of Reduce and kronecker. } \examples{ kprod(diag(2), t(ones(2))) kprod(t(ones(2)), diag(2)) kprod(diag(2), t(ones(2)), t(ones(2))) kprod(t(ones(2)), diag(2), t(ones(2))) kprod(t(ones(2)), t(ones(2)), diag(2)) # cf. aoki, hara, and takemura p.13 rbind( kprod(diag(2), t(ones(2))), kprod(t(ones(2)), diag(2)) ) } latte/DESCRIPTION0000644000176200001440000000253715021467402013101 0ustar liggesusersPackage: latte Type: Package Title: Interface to 'LattE' and '4ti2' Version: 0.2.2 Authors@R: c(person("David", "Kahle", email = "david@kahle.io", role = c("aut", "cph", "cre"), comment = c(ORCID = "0000-0002-9999-1558")), person("Luis", "Garcia",email = "lgarcia@shsu.edu", role = c("aut", "cph")), person("Ruriko", "Yoshida", email = "ryoshida@nps.edu", role = c("aut", "cph"))) Maintainer: David Kahle Description: Back-end connections to 'LattE' () for counting lattice points and integration inside convex polytopes and '4ti2' () for algebraic, geometric, and combinatorial problems on linear spaces and front-end tools facilitating their use in the 'R' ecosystem. License: GPL-2 URL: https://github.com/dkahle/latte BugReports: https://github.com/dkahle/latte/issues SystemRequirements: LattE , 4ti2 Imports: magrittr, stringr, mpoly, ggplot2, memoise, dplyr, usethis, glue Suggests: knitr, rmarkdown RoxygenNote: 7.3.2 Encoding: UTF-8 NeedsCompilation: no Packaged: 2025-06-09 05:07:18 UTC; david_kahle Author: David Kahle [aut, cph, cre] (ORCID: ), Luis Garcia [aut, cph], Ruriko Yoshida [aut, cph] Repository: CRAN Date/Publication: 2025-06-09 05:20:02 UTC