diff --git a/DESCRIPTION b/DESCRIPTION index bd1f475d..ad794bb0 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -21,6 +21,7 @@ Roxygen: list(wrap = FALSE) Imports: BBmisc (>= 1.10), checkmate (>= 1.8.2), + stringi, methods Suggests: akima, diff --git a/NAMESPACE b/NAMESPACE index 821b2ec2..cfbc7cd4 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -162,6 +162,7 @@ export(makeParamSet) export(makeUntypedLearnerParam) export(makeUntypedParam) export(paramValueToString) +export(parsePCSFile) export(plotEAF) export(plotOptPath) export(plotYTraces) @@ -180,6 +181,7 @@ import(BBmisc) import(checkmate) import(methods) import(stats) +import(stringi) useDynLib(ParamHelpers,c_dfRowsToList) useDynLib(ParamHelpers,c_generateDesign) useDynLib(ParamHelpers,c_trafo_and_set_dep_to_na) diff --git a/R/parsePCSFile.R b/R/parsePCSFile.R new file mode 100644 index 00000000..484fc07a --- /dev/null +++ b/R/parsePCSFile.R @@ -0,0 +1,86 @@ +consume = function(s, regexp) { + loc = stri_locate_first_regex(s, regexp)[1L, ] + e = stri_sub(s, loc[1L], loc[2L]) + r = stri_join(stri_sub(s, 1L, loc[1L] - 1L), stri_sub(s, loc[2L] + 1L, stri_length(s))) + list(match = stri_trim_both(e), rest = stri_trim_both(r)) +} + +parseDefault = function(s) { + s = consume(s, "\\[.*\\]") + stri_trim_both(stri_replace_all_regex(s$match, "[\\[\\]]", "")) +} + +stri_split_trim = function(x, sep = ",") { + stri_trim_both(stri_split_fixed(x, sep)[[1L]]) +} + +#' @title Read and parse PCS files +#' +#' @param file [\code{character(1)}].\cr +#' Path to the PCS file. +#' @return \code{\link{ParamSet}}. +#' @export +parsePCSFile = function(file) { + assertFileExists(file, access = "r", extension = "pcs") + + lines = stri_read_lines(file) + lines = stri_replace_all_regex(lines, "#.*", "") + lines = stri_trim_both(lines) + lines = lines[nzchar(lines)] + result = list() + + lines = lines[!stri_startswith_fixed(lines, "Conditionals:")] + j = stri_detect_fixed(lines, "|") + lines.cond = lines[j] + lines = lines[!j] + + lines = lines[!stri_startswith_fixed(lines, "Forbidden:")] + j = stri_startswith_fixed(lines, "{") & stri_endswith_fixed(lines, "}") + lines.forbidden = lines[j] + lines = lines[!j] + + ### parse param lines + for (line in lines) { + z = consume(line, "[a-zA-Z0-9_\\-]+\\s*") + id = z$match + + if (stri_startswith_fixed(z$rest, "[")) { # num or int param + z = consume(z$rest, "^\\[.*?\\]") + bounds = stri_replace_all_regex(z$match, "[\\[\\]]", "") + bounds = as.numeric(stri_split_trim(bounds)) + if (stri_detect_fixed(z$rest, "i")) { + def = as.numeric(parseDefault(z$rest)) + par = makeIntegerParam(id = id, lower = bounds[1L], upper = bounds[2L], default = def) + } else { + def = as.integer(parseDefault(z$rest)) + par = makeNumericParam(id = id, lower = bounds[1L], upper = bounds[2L], default = def) + } + } else if (stri_startswith_fixed(z$rest, "{")) { # discrete + z = consume(z$rest, "^\\{.*\\}") + values = stri_replace_all_regex(z$match, "[{}]", "") + values = stri_split_trim(values) + def = parseDefault(z$rest) + par = makeDiscreteParam(id = id, values = values, default = def) + } else { + stop("Illegal format") + } + result[[id]] = par + } + + for (line in lines.cond) { + s = stri_split_trim(line, "|") + id1 = s[1L] + stopifnot(id %in% names(result)) + + s = stri_split_trim(s[2L], " in ") + id2 = s[1L] + stopifnot(id2 %in% names(result)) + + vals = stri_split_trim(stri_replace_all_regex(s[2L], "[{}]", "")) + req = sprintf("%s %%in%% c('%s')", id2, stri_flatten(vals, "','")) + req = quote(req) + result[[id1]]$requires = req + } + + result +} diff --git a/R/pcs_helpers.R b/R/pcs_helpers.R new file mode 100644 index 00000000..e1019ac5 --- /dev/null +++ b/R/pcs_helpers.R @@ -0,0 +1,4 @@ +filterEmptyStrings = function(xs) { + xs = vcapply(xs, stri_trim) + xs[nzchar(xs)] +} diff --git a/R/writePCSFile.R b/R/writePCSFile.R new file mode 100644 index 00000000..4672b8fa --- /dev/null +++ b/R/writePCSFile.R @@ -0,0 +1,35 @@ +#' @title Writes a param set to a PCS files. +#' +#' @description +#' +#' @template arg_parset +#' @param path [\code{character(1)}]\cr +#' File path for output PCS file. +#' @param overwrite [\code{logical(1)}]\cr +#' Can \code{path} be overwritten? +#' Default is \code{FALSE}. +#' @return Nothing. +#' @family ParamSet, pcs +writePCSFile = function(par.set, path, overwrite = FALSE) { + assertClass(par.set, "ParamSet") + assertPathForOutput(path, overwrite = overwrite) + assertFlag(overwrite) + lines = character(0L) # result container + + # write line for a scalar (nonvec) param, returns string + writePCSScalarLine = function(p) { + s = sprintf("%s [%g,%g] [%g]", p$id, p$lower, p$upper, p$default) + # print(s) + return(s) + } + + # loop over params, loop over length of vectors, add line to "lines" + for (p in par.set$pars) { + len = p$len + for (j in 1:p$len) { + lines[length(lines) + 1L] = writePCSScalarLine(p) + } + } + stri_write_lines(fname = path, str = lines) + invisible(NULL) +} diff --git a/R/zzz.R b/R/zzz.R index b33c7a4b..aba7a76c 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -2,4 +2,5 @@ #' @import checkmate #' @import methods #' @import stats +#' @import stringi NULL diff --git a/inst/pcs_files/branin-params.R b/inst/pcs_files/branin-params.R new file mode 100644 index 00000000..9c077e22 --- /dev/null +++ b/inst/pcs_files/branin-params.R @@ -0,0 +1,5 @@ +ps = makeParamSet( + makeNumericParam("x0", lower = -5, upper = 10, default = 10), + makeNumericParam("x1", lower = 0, upper = 15, default = 15) +) + diff --git a/inst/pcs_files/branin-params.pcs b/inst/pcs_files/branin-params.pcs new file mode 100755 index 00000000..f9fdaee4 --- /dev/null +++ b/inst/pcs_files/branin-params.pcs @@ -0,0 +1,3 @@ +x0 [-5,10] [10] +x1 [0, 15] [15] + diff --git a/inst/pcs_files/camelback-params.R b/inst/pcs_files/camelback-params.R new file mode 100644 index 00000000..7b07bf76 --- /dev/null +++ b/inst/pcs_files/camelback-params.R @@ -0,0 +1,8 @@ +x0 [-3,3] [3] +x1 [-2, 2] [2] + +ps = makeParamSet( + makeNumericParam("x0", lower = -3, upper = 3, default = 3), + makeNumericParam("x1", lower = -2, upper = 2, default = 2) +) + diff --git a/inst/pcs_files/camelback-params.pcs b/inst/pcs_files/camelback-params.pcs new file mode 100755 index 00000000..c9690338 --- /dev/null +++ b/inst/pcs_files/camelback-params.pcs @@ -0,0 +1,2 @@ +x0 [-3,3] [3] +x1 [-2, 2] [2] \ No newline at end of file diff --git a/inst/pcs_files/cplex12-params-milp.pcs b/inst/pcs_files/cplex12-params-milp.pcs new file mode 100755 index 00000000..f5e525bc --- /dev/null +++ b/inst/pcs_files/cplex12-params-milp.pcs @@ -0,0 +1,80 @@ +barrier_limits_growth {1e+6,1e+8,1e+10,1e+12,1e+14}[1e+12] # barrier growth limit. Allegedly called bargrowth. in R, >= 1.0. Now that I check results numerically this can be optimized +barrier_algorithm {0,1,2,3}[0] # barrier algorithm. Auto, cat +barrier_crossover {-1,0,1,2}[0] # barrier crossover algorithm. Auto, cat +barrier_limits_corrections {-1,0,1,4,16,64}[-1] # barrier maximum correction limit. Auto=-1, in N+, poorly informed +barrier_ordering {0,1,2,3} [0] # barrier ordering algorithm. Auto, cat +barrier_startalg {1,2,3,4}[1] # barrier starting point algorithm. Auto, cat +emphasis_memory {no}[no] #MEMORYEMPHASIS. No auto. Binary. Disallow emphasis_memory yes. +emphasis_mip {0,1,2,3,4}[0] # MIP emphasis switch. Auto, cat +emphasis_numerical {yes,no}[no] # numerical precision emphasis. No auto, cat. Since I penalize (too) poor numerical precision this is an optimization parameter +feasopt_mode {0,1,2,3,4,5}[0] # mode of FeasOpt. Auto, cat +lpmethod {0,1,2,3,4,5,6}[0] # algorithm for continuous problems. Auto, cat +mip_cuts_cliques {-1,0,1,2,3}[0] # MIP cliques switch. Auto, cat +mip_cuts_covers {-1,0,1,2,3}[0] # MIP covers switch. Auto, cat +mip_cuts_disjunctive {-1,0,1,2,3}[0] # MIP disjunctive cuts switch. Auto, cat +mip_cuts_flowcovers {-1,0,1,2}[0] # MIP flow cover cuts switch. Auto, cat +mip_cuts_gomory {-1,0,1,2}[0] # MIP Gomory fractional cuts switch. Auto, cat +mip_cuts_gubcovers {-1,0,1,2}[0] # MIP GUB cuts switch. Auto, cat +mip_cuts_implied {-1,0,1,2}[0] # MIP implied bound cuts switch. Auto, cat +mip_cuts_mcfcut {-1,0,1,2}[0] # MCF cut switch. Auto, cat +mip_cuts_mircut {-1,0,1,2}[0] # MIP MIR (mixed integer rounding) cut switch. Auto, cat +mip_cuts_pathcut {-1,0,1,2}[0] # MIP flow path cut switch. Auto, cat +mip_cuts_zerohalfcut {-1,0,1,2} [0] # MIP zero-half cuts switch. Auto, cat +mip_limits_aggforcut {0,1,2,3,5,10}[3] # constraint aggregation limit for cut generation. No auto, in N+_0 +mip_limits_cutsfactor {1,2,4,8,16}[4] # row multiplier factor for cuts. in R+ +mip_limits_cutpasses {-1,0,1,4,16,64}[0] # number of cutting plane passes. Auto=0, in N+, poorly informed +mip_limits_gomorycand {50,100,200,400,800}[200] # candidate limit for generating Gomory fractional cuts. No auto, in N+ +mip_limits_gomorypass {0,1,4,16,64}[0] # pass limit for generating Gomory fractional cuts. Auto=0, in N+, poorly informed +mip_limits_strongcand {2,5,10,20,40}[10] # MIP strong branching candidate list limit. No auto, in N_0+ +mip_limits_strongit {0,1,4,16,64}[0] # MIP strong branching iterations limit. Auto=0, in N+ , poorly informed +mip_limits_submipnodelim {125,250,500,1000,2000}[500] # limit on nodes explored when a subMIP is being solved. No auto, in N_0+ +mip_ordertype {0,1,2,3}[0] # MIP priority order generation. No auto, cat +mip_strategy_backtrack {0.9,0.99,0.999,0.9999,0.99999,0.999999} [0.9999] # backtracking tolerance. No auto, any number from 0.0 to 1.0. Despite the name this is not a tolerance parameter +mip_strategy_bbinterval {2,4,7,15,30,1000}[7] # MIP strategy best bound interval. No auto, in N+_0. 0 is equivalent to infinity +mip_strategy_branch {-1,0,1} [0] # MIP branching direction. Auto, cat +mip_strategy_dive {0,1,2,3}[0] # MIP dive strategy. Auto, cat +mip_strategy_file {0,1}[1] #node storage file switch. No auto. Cat. DISALLOW values 2 and 3 => they write files to disk (stuff will break and we run out of space) +mip_strategy_fpheur {-1,0,1,2}[0] # feasibility pump switch. Auto, cat. Does NOT apply for MIQCP +mip_strategy_heuristicfreq {-1,0,5,10,20,40,80}[0] # MIP heuristic frequency. Auto=0, in N+. 20 is an example used in the manual. It may be totally off... +mip_strategy_lbheur {yes,no}[no] # local branching heuristic. No auto, cat +mip_strategy_nodeselect {0,1,2,3}[1] # MIP node selection strategy. No auto, cat +mip_strategy_order {yes,no}[yes] # MIP priority order switch. No auto, cat. +mip_strategy_presolvenode {-1,0,1,2}[0] # node presolve switch. Auto, cat +mip_strategy_probe {-1,0,1,2,3}[0] # MIP probing level. Auto, cat +mip_strategy_rinsheur {-1,0,5,10,20,40,80}[0] # RINS heuristic frequency. Auto=0, 20 is an example from the CPLEX parameter reference; could be totally off +mip_strategy_search {0,1,2} [0] # MIP dynamic search switch. Auto, cat. NOT compatible with callbacks (fine in our case, where we don't use those) +mip_strategy_startalgorithm {0,1,2,3,4,5,6}[0] # MIP starting algorithm. Auto, cat. SPECIAL CASES: MIQCP and MIQP only allow some of these +mip_strategy_subalgorithm {0,1,2,3,4,5}[0] # MIP subproblem algorithm. Auto, cat. +mip_strategy_variableselect {-1,0,1,2,3,4} [0] # MIP variable selection strategy. Auto, cat +network_netfind {1,2,3}[2] # simplex network extraction level. No auto, cat +network_pricing {0,1,2}[0] # network simplex pricing algorithm. Auto, cat. The CPLEX parameter reference says the default (0) is identical to option 3, which I thus disabled. +perturbation_constant {1e-8,1e-7,1e-6,1e-5,1e-4}[1e-6] # part 2 of parameter "simplex_perturbation", conditional on part1=1 +preprocessing_aggregator {-1,0,1,4,16,64}[-1] # preprocessing aggregator application limit +preprocessing_boundstrength {-1,0,1}[-1] # bound strengthening switch. Auto, cat +preprocessing_coeffreduce {0,1,2} [2] # coefficient reduction setting. Auto, cat +preprocessing_dependency {-1,0,1,2,3}[-1] # dependency switch. Auto, cat +preprocessing_dual {-1,0,1}[0] # presolve dual setting. Auto, cat +preprocessing_fill {2,5,10,20,40}[10] # preprocessing aggregator fill. No auto, in N+ +preprocessing_linear {0,1}[1] # linear reduction switch. No auto, cat +preprocessing_numpass {-1,0,1,4,16,64}[-1] # limit on the number of presolve passes made. Auto=-1, in N+, poorly informed +preprocessing_reduce {0,1,2,3}[3] # primal and dual reduction type. Auto, cat +preprocessing_relax {-1,0,1}[-1] # relaxed LP presolve switch. Auto, cat +preprocessing_repeatpresolve {-1,0,1,2,3}[-1] # MIP repeat presolve switch. Auto, cat +preprocessing_symmetry {-1,0,1,2,3,4,5} [-1] # symmetry breaking. Auto, cat +read_scale {-1,0,1}[0] # scale parameter. Auto, cat +sifting_algorithm {0,1,2,3,4}[0] # sifting subproblem algorithm. Auto, cat. +simplex_crash {-1,0,1}[1] # simplex crash ordering. Auto, cat +simplex_dgradient {0,1,2,3,4,5}[0] # dual simplex pricing algorithm. Auto, cat +simplex_limits_perturbation {0,1,4,16,64}[0] # simplex perturbation limit. Auto=0, in N+, poorly informed +simplex_limits_singularity {2,5,10,20,40}[10] # simplex singularity repair limit. No auto, in N_0+ +simplex_perturbation_switch {no,yes}[no] # part 1 of parameter "simplex_perturbation" +simplex_pgradient {-1,0,1,2,3,4}[0] # primal simplex pricing algorithm. Auto, cat +simplex_pricing {0,1,4,16,64}[0] # simplex pricing candidate list size. Auto=0, in N+, poorly informed +simplex_refactor {0,4,16,64,256} [0] #simplex refactoring frequency. 0=Auto. N+. Simplex refactorization interval. Hoyt's LP notes say Chvtal suggests an optimal refactorization interval of 16. +simplex_tolerances_markowitz {0.0001, 0.001, 0.01, 0.1, 0.5} [0.01] # Markowitz tolerance. 0.0001 to 0.99999 + +Conditionals: +mip_limits_strongcand | mip_strategy_variableselect in {3} +mip_limits_strongit | mip_strategy_variableselect in {3} +mip_strategy_order | mip_ordertype in {1,2,3} +perturbation_constant | simplex_perturbation_switch in {yes} diff --git a/inst/pcs_files/saps-params.R b/inst/pcs_files/saps-params.R new file mode 100644 index 00000000..d6685fae --- /dev/null +++ b/inst/pcs_files/saps-params.R @@ -0,0 +1,12 @@ +# alpha [1, 1.4] [1.189]l +# rho [0, 1] [0.5] +# ps [0, 0.2] [0.1] +# wp [0, 0.06] [0.03] + +ps = makeParamSet( + makeNumericParam("alpha", lower = -5, upper = 10, default = 10), + makeNumericParam("rho", lower = 0, upper = 15, default = 15), + makeNumericParam("ps", lower = 0, upper = 15, default = 15), + makeNumericParam("wp", lower = 0, upper = 15, default = 15) +) + diff --git a/inst/pcs_files/saps-params.pcs b/inst/pcs_files/saps-params.pcs new file mode 100755 index 00000000..9e13837b --- /dev/null +++ b/inst/pcs_files/saps-params.pcs @@ -0,0 +1,4 @@ +alpha [1, 1.4] [1.189]l +rho [0, 1] [0.5] +ps [0, 0.2] [0.1] +wp [0, 0.06] [0.03] \ No newline at end of file diff --git a/inst/pcs_files/spear-params-mixed.pcs b/inst/pcs_files/spear-params-mixed.pcs new file mode 100755 index 00000000..b51c658b --- /dev/null +++ b/inst/pcs_files/spear-params-mixed.pcs @@ -0,0 +1,38 @@ +sp-var-dec-heur {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}[0] # Originally, 3,4,9,10 not used following Domagoj's advice. 20 requires modular arithmetic input format +sp-learned-clause-sort-heur {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}[0] # All values make sense here. 20 requires modular arithmetic input format +sp-orig-clause-sort-heur {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}[0] # All values make sense here. 20 requires modular arithmetic input format +sp-res-order-heur {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}[0] # All values make sense here. 20 requires modular arithmetic input format +sp-clause-del-heur {0,1,2}[2] # All values make sense here. +sp-phase-dec-heur {0,1,2,3,4,5,6}[5] # All values make sense here. +sp-resolution {0,1,2}[1] # 0 renders a whole bunch of conditionals irrelevant. +sp-variable-decay [1, 2] [1.4]l # Should be bigger than 1 (o/w increase not decay). Was: in 1.1,1.4,2.0, def 1.4 +sp-clause-decay [1, 2] [1.4]l # Same thing. +sp-restart-inc [1.1, 1.9] [1.5] # Uniform because multiplicative. Was: in 1.1,1.3,1.5,1.7,1.9, def 1.5 +sp-learned-size-factor [0.1, 1.6] [0.4]l # Uniform on logarithmic scale (starting value). Was: in 0.1,0.2,0.4,0.8,1.6, def 0.4 +sp-learned-clauses-inc [1.1, 1.5] [1.3] # 1.2 and 1.4 were introduced later. Uniform because multiplicative Was: in1.1,1.2,1.3,1.4,1.5, def 1.3 +sp-clause-activity-inc [0.5, 1.5] [1] # Was: in 0.5,1,1.5, def 1 +sp-var-activity-inc [0.5, 1.5] [1] # Was: in 0.5,1,1.5, def 1 +sp-rand-phase-dec-freq{0, 0.0001, 0.001, 0.005, 0.01, 0.05}[0.001] # Used discretized version to preserve 0. Never picked 0.05 in previous experiments, always zero. +sp-rand-var-dec-freq {0, 0.0001, 0.001, 0.005, 0.01, 0.05}[0.001] # Used discretized version to preserve 0. Never picked 0.05 in previous experiments, always zero. +sp-rand-var-dec-scaling [0.3, 1.1] [1] # Domagoj said the previous values were too coarse, so finer discretization now. +sp-rand-phase-scaling [0.3, 1.1] [1] # Same thing. Was: in 0.3,0.6,0.9,1,1.1, def 1 +sp-max-res-lit-inc [0.25, 4][1]l # 0.5 and 2 were introduced later. Was: in 0.25,0.5,1,2,4, def 1 +sp-first-restart [25, 3200] [100]il # Uniform on logarithmic scale (starting value). Was: in 25,50,100,200,400,800,1600,3200, def 100 +sp-res-cutoff-cls [2, 20] [8]il # Only up to 20 allowed, would've used 32 otherwise. +sp-res-cutoff-lits [100, 1600] [400]il # Was: in 100,200,400,800,1600, def 400 +sp-max-res-runs [1, 32] [4]il # Was: in 1,2,4,8,16,32, def 4 +sp-update-dec-queue {0,1}[1] # Enable by default. +sp-use-pure-literal-rule {0,1}[1] # Enable by default. +sp-clause-inversion {0,1}[1] # Enable by default. Enable reversion of learned clauses if fixed order (sp-learned-clause-sort-heur=19) + +Conditionals: +sp-rand-phase-dec-freq|sp-phase-dec-heur in {0,1,3,4,5,6} # when heuristic is random, then additional random steps don't change anything +sp-rand-var-dec-scaling|sp-rand-var-dec-freq in {0.0001, 0.001, 0.005, 0.01, 0.05} # not 0 +sp-rand-phase-scaling|sp-rand-phase-dec-freq in {0.0001, 0.001, 0.005, 0.01, 0.05} # not 0 +sp-clause-inversion|sp-learned-clause-sort-heur in {19} + +sp-res-order-heur|sp-resolution in {1,2} +sp-max-res-lit-inc|sp-resolution in {1,2} +sp-res-cutoff-cls|sp-resolution in {1,2} +sp-res-cutoff-lits|sp-resolution in {1,2} +sp-max-res-runs|sp-resolution in {1,2} \ No newline at end of file diff --git a/man/parsePCSFile.Rd b/man/parsePCSFile.Rd new file mode 100644 index 00000000..8849cee2 --- /dev/null +++ b/man/parsePCSFile.Rd @@ -0,0 +1,15 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/parsePCSFile.R +\name{parsePCSFile} +\alias{parsePCSFile} +\title{Read and parse PCS files} +\usage{ +parsePCSFile(file) +} +\arguments{ +\item{file}{[\code{character(1)}].\cr +Path to the PCS file.} +} +\value{ +\code{\link{ParamSet}}. +} diff --git a/man/writePCSFile.Rd b/man/writePCSFile.Rd new file mode 100644 index 00000000..a1a3272a --- /dev/null +++ b/man/writePCSFile.Rd @@ -0,0 +1,25 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/writePCSFile.R +\name{writePCSFile} +\alias{writePCSFile} +\title{Writes a param set to a PCS files.} +\usage{ +writePCSFile(par.set, path, overwrite = FALSE) +} +\arguments{ +\item{par.set}{[\code{\link{ParamSet}}]\cr +Parameter set.} + +\item{path}{[\code{character(1)}]\cr +File path for output PCS file.} + +\item{overwrite}{[\code{logical(1)}]\cr +Can \code{path} be overwritten? +Default is \code{FALSE}.} +} +\value{ +Nothing. +} +\description{ + +} diff --git a/test.R b/test.R new file mode 100644 index 00000000..e6e7f1b5 --- /dev/null +++ b/test.R @@ -0,0 +1,9 @@ +load_all() + +ps = makeParamSet( + makeNumericParam("x0", lower = -5, upper = 10, default = 10), + makeNumericParam("x1", lower = 0, upper = 15, default = 15 ) +) + + +writePCSFile(ps, path = "~/cos/ParamHelpers/bla.pcs", overwrite = TRUE) diff --git a/tests/testthat/test_parsePCSFile.R b/tests/testthat/test_parsePCSFile.R new file mode 100644 index 00000000..5dfea56f --- /dev/null +++ b/tests/testthat/test_parsePCSFile.R @@ -0,0 +1,40 @@ +context("parsePCSFile") + +test_that("parsePCSFile ", { + path = system.file("inst/pcs_files", package = "ParamHelpers") + fns = list.files(path, pattern = ".pcs", full.names = TRUE) + + #FIXME: loop over all! + + + # read a pcs file, trim WS, and remove all empty lines + readPCSLines = function(path) { + lines = stri_read_lines(fn) + lines = vcapply(lines, str_trim) + lines[nzchar(lines)] + } + + + for (fn in fns[1]) { + # print(fn) + # parse normal PCS files + # ps = parsePCSFile(fn) + # parse mathing R file into envir + fnr = stri_replace(fn, fixed = ".pcs", ".R") + # print(fnr) + ee = new.env() + source(fnr, local = ee) + + # check that parsed result matches manual paramset R file + # expect_equal(ps, ee$ps, info = sprintf("pcs parser: %s", fn)) + + # check that writer works + outpath = tempfile() + writePCSFile(ee$ps, outpath) + lines1 = readPCSLines(fn) + # print(lines1) + lines2 = readPCSLines(outpath) + # print(lines2) + expect_equal(lines1, lines2, info = sprintf("pcs writer: %s", fnr)) + } +})