ParamHelpers/0000755000176000001440000000000014260547430012672 5ustar ripleyusersParamHelpers/NAMESPACE0000644000176000001440000001163613636350110014111 0ustar ripleyusers# Generated by roxygen2: do not edit by hand S3method(addOptPathEl,OptPathDF) S3method(as.data.frame,OptPathDF) S3method(c,ParamSet) S3method(evaluateParamExpressions,Param) S3method(evaluateParamExpressions,ParamSet) S3method(evaluateParamExpressions,list) S3method(getDefaults,Param) S3method(getDefaults,ParamSet) S3method(getDefaults,list) S3method(getOptPathCol,OptPathDF) S3method(getOptPathCols,OptPathDF) S3method(getOptPathDOB,OptPathDF) S3method(getOptPathEOL,OptPathDF) S3method(getOptPathEl,OptPathDF) S3method(getOptPathErrorMessages,OptPathDF) S3method(getOptPathExecTimes,OptPathDF) S3method(getOptPathLength,OptPathDF) S3method(getOptPathX,OptPathDF) S3method(getOptPathY,OptPathDF) S3method(getParamIds,Param) S3method(getParamIds,ParamSet) S3method(getParamLengths,Param) S3method(getParamLengths,ParamSet) S3method(getValues,Param) S3method(getValues,ParamSet) S3method(getValues,list) S3method(hasExpression,LearnerParam) S3method(hasExpression,LearnerParamSet) S3method(hasExpression,Param) S3method(hasExpression,ParamSet) S3method(hasExpression,list) S3method(hasFiniteBoxConstraints,Param) S3method(hasFiniteBoxConstraints,ParamSet) S3method(hasRequires,Param) S3method(hasRequires,ParamSet) S3method(hasTrafo,Param) S3method(hasTrafo,ParamSet) S3method(isCharacter,Param) S3method(isCharacter,ParamSet) S3method(isDiscrete,Param) S3method(isDiscrete,ParamSet) S3method(isEmpty,ParamSet) S3method(isFeasible,LearnerParam) S3method(isFeasible,Param) S3method(isFeasible,ParamSet) S3method(isInteger,Param) S3method(isInteger,ParamSet) S3method(isLogical,Param) S3method(isLogical,ParamSet) S3method(isNumeric,Param) S3method(isNumeric,ParamSet) S3method(isVector,Param) S3method(isVector,ParamSet) S3method(paramValueToString,Param) S3method(paramValueToString,ParamSet) S3method(print,LearnerParam) S3method(print,OptPath) S3method(print,Param) S3method(print,ParamSet) S3method(sampleValue,Param) S3method(sampleValue,ParamSet) S3method(setValueCNames,Param) S3method(setValueCNames,ParamSet) export(addOptPathEl) export(checkParamSet) export(convertParamSetToIrace) export(dfRowToList) export(dfRowsToList) export(discreteNameToValue) export(discreteValueToName) export(dropParams) export(evaluateParamExpressions) export(filterParams) export(filterParamsDiscrete) export(filterParamsNumeric) export(generateDesign) export(generateDesignOfDefaults) export(generateGridDesign) export(generateRandomDesign) export(getDefaults) export(getLower) export(getOptPathBestIndex) export(getOptPathCol) export(getOptPathCols) export(getOptPathDOB) export(getOptPathEOL) export(getOptPathEl) export(getOptPathErrorMessages) export(getOptPathExecTimes) export(getOptPathLength) export(getOptPathParetoFront) export(getOptPathX) export(getOptPathY) export(getParamIds) export(getParamLengths) export(getParamNr) export(getParamSet) export(getParamTypeCounts) export(getParamTypes) export(getRequirements) export(getTypeStringsAll) export(getTypeStringsCharacter) export(getTypeStringsDiscrete) export(getTypeStringsInteger) export(getTypeStringsLogical) export(getTypeStringsNumeric) export(getTypeStringsNumericStrict) export(getUpper) export(getValues) export(hasCharacter) export(hasDiscrete) export(hasExpression) export(hasFiniteBoxConstraints) export(hasForbidden) export(hasInteger) export(hasLogical) export(hasNumeric) export(hasRequires) export(hasTrafo) export(isCharacter) export(isCharacterTypeString) export(isDiscrete) export(isDiscreteTypeString) export(isEmpty) export(isFeasible) export(isForbidden) export(isInteger) export(isIntegerTypeString) export(isLogical) export(isLogicalTypeString) export(isNumeric) export(isNumericTypeString) export(isRequiresOk) export(isSpecialValue) export(isVector) export(isVectorTypeString) export(makeCharacterParam) export(makeCharacterVectorParam) export(makeDiscreteLearnerParam) export(makeDiscreteParam) export(makeDiscreteVectorLearnerParam) export(makeDiscreteVectorParam) export(makeFunctionLearnerParam) export(makeFunctionParam) export(makeIntegerLearnerParam) export(makeIntegerParam) export(makeIntegerVectorLearnerParam) export(makeIntegerVectorParam) export(makeLogicalLearnerParam) export(makeLogicalParam) export(makeLogicalVectorLearnerParam) export(makeLogicalVectorParam) export(makeNumericLearnerParam) export(makeNumericParam) export(makeNumericParamSet) export(makeNumericVectorLearnerParam) export(makeNumericVectorParam) export(makeOptPathDF) export(makeParamSet) export(makeUntypedLearnerParam) export(makeUntypedParam) export(paramValueToString) export(plotEAF) export(plotOptPath) export(plotYTraces) export(removeMissingValues) export(renderOptPathPlot) export(repairPoint) export(sampleValue) export(sampleValues) export(setOptPathElDOB) export(setOptPathElEOL) export(setValueCNames) export(trafoOptPath) export(trafoValue) export(updateParVals) import(BBmisc, except = isFALSE) import(checkmate) import(methods) import(stats) importFrom(fastmatch,"%fin%") importFrom(fastmatch,fmatch) useDynLib(ParamHelpers,c_dfRowsToList) ParamHelpers/LICENSE0000644000176000001440000000011113164130622013661 0ustar ripleyusersYEAR: 2013-2017 COPYRIGHT HOLDER: Bernd Bischl, Michel Lang, Daniel Horn ParamHelpers/man/0000755000176000001440000000000013636346430013450 5ustar ripleyusersParamHelpers/man/OptPath.Rd0000644000176000001440000000716113633666270015327 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/OptPath.R, R/OptPathDF.R \name{OptPath} \alias{OptPath} \alias{makeOptPathDF} \alias{OptPathDF} \title{Create optimization path.} \usage{ makeOptPathDF( par.set, y.names, minimize, add.transformed.x = FALSE, include.error.message = FALSE, include.exec.time = FALSE, include.extra = FALSE ) } \arguments{ \item{par.set}{\link{ParamSet}\cr Parameter set.} \item{y.names}{(\code{character})\cr Names of performance measures that are optimized or logged.} \item{minimize}{(\code{logical})\cr Which of the performance measures in y.names should be minimized? Vector of booleans in the same order as \code{y.names}.} \item{add.transformed.x}{(\code{logical(1)})\cr If some parameters have associated transformations, are you going to add x values after they have been transformed? Default is \code{FALSE}.} \item{include.error.message}{(\code{logical(1)})\cr Should it be possible to include an error message string (or NA if no error occurred) into the path for each evaluation? This is useful if you have complex, long running objective evaluations that might fail. Default is \code{FALSE}.} \item{include.exec.time}{(\code{logical(1)})\cr Should it be possible to include execution time of evaluations into the path for each evaluation? Note that execution time could also be entered in \code{y.names} as a direct performance measure. If you use this option here, time is regarded as an extra measurement you might be curious about. Default is \code{FALSE}.} \item{include.extra}{(\code{logical(1)})\cr Should it be possible to include extra info into the path for each evaluation? Default is \code{FALSE}.} } \description{ Optimizers can iteratively log their evaluated points into this object. Can be converted into a data.frame with \code{as.data.frame(x, discretes.as.factor = TRUE / FALSE)}. A optimization path has a number of path elements, where each element consists of: the value of the decision variables at this point, the values of the performance measures at this point, the date-of-birth (dob) of this point, the end-of-life (eol) of this point and possibly an error message. See also \code{\link[=addOptPathEl]{addOptPathEl()}}. For discrete parameters always the name of the value is stored as a character. When you retrieve an element with \code{\link[=getOptPathEl]{getOptPathEl()}}, this name is converted to the actual discrete value. If parameters have associated transformation you are free to decide whether you want to add x values before or after transformation, see argument \code{add.transformed.x} and \code{\link[=trafoOptPath]{trafoOptPath()}}. The S3 class is a list which stores at least these elements: \describe{ \item{par.set \code{\link[=ParamSet]{ParamSet()}}}{See argument of same name.} \item{y.names \code{\link{character}}}{See argument of same name.} \item{minimize \code{\link{logical}}}{See argument of same name.} \item{add.transformed.x \code{logical(1)}}{See argument of same name.} \item{env \code{\link{environment}}}{Environment which stores the optimization path. Contents depend on implementation.} } } \seealso{ Other optpath: \code{\link{addOptPathEl}()}, \code{\link{getOptPathBestIndex}()}, \code{\link{getOptPathCols}()}, \code{\link{getOptPathCol}()}, \code{\link{getOptPathDOB}()}, \code{\link{getOptPathEOL}()}, \code{\link{getOptPathEl}()}, \code{\link{getOptPathErrorMessages}()}, \code{\link{getOptPathExecTimes}()}, \code{\link{getOptPathLength}()}, \code{\link{getOptPathParetoFront}()}, \code{\link{getOptPathX}()}, \code{\link{getOptPathY}()}, \code{\link{setOptPathElDOB}()}, \code{\link{setOptPathElEOL}()} } \concept{optpath} ParamHelpers/man/getOptPathCols.Rd0000644000176000001440000000262013633666270016643 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/OptPath_getter.R \name{getOptPathCols} \alias{getOptPathCols} \title{Get columns from the optimization path.} \usage{ getOptPathCols(op, names, dob, eol, row.names = NULL) } \arguments{ \item{op}{\link{OptPath}\cr Optimization path.} \item{names}{\link{character}\cr Names of the columns.} \item{dob}{\link{integer}\cr Vector of date-of-birth values to further subset the result. Only elements with a date-of-birth included in \code{dob} are selected. Default is all.} \item{eol}{\link{integer}\cr Vector of end-of-life values to further subset the result. Only elements with an end-of-life included in \code{eol} are selected. Default is all.} \item{row.names}{\link{character}\cr Row names for result. Default is none.} } \value{ \link{data.frame}. } \description{ Get columns from the optimization path. } \seealso{ Other optpath: \code{\link{OptPath}}, \code{\link{addOptPathEl}()}, \code{\link{getOptPathBestIndex}()}, \code{\link{getOptPathCol}()}, \code{\link{getOptPathDOB}()}, \code{\link{getOptPathEOL}()}, \code{\link{getOptPathEl}()}, \code{\link{getOptPathErrorMessages}()}, \code{\link{getOptPathExecTimes}()}, \code{\link{getOptPathLength}()}, \code{\link{getOptPathParetoFront}()}, \code{\link{getOptPathX}()}, \code{\link{getOptPathY}()}, \code{\link{setOptPathElDOB}()}, \code{\link{setOptPathElEOL}()} } \concept{optpath} ParamHelpers/man/hasFiniteBoxConstraints.Rd0000644000176000001440000000143113633666270020555 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/hasFiniteBoxConstraints.R \name{hasFiniteBoxConstraints} \alias{hasFiniteBoxConstraints} \title{Checks if a parameter or each parameter of a parameter set has ONLY finite lower and upper bounds.} \usage{ hasFiniteBoxConstraints(par, dict = NULL) } \arguments{ \item{par}{(\link{Param} | \link{ParamSet})\cr Parameter or parameter set.} \item{dict}{(\code{environment} | \link{list} | \code{NULL})\cr Environment or list which will be used for evaluating the variables of expressions within a parameter, parameter set or list of parameters. The default is \code{NULL}.} } \value{ \code{logical(1)} } \description{ Checks if a parameter or each parameter of a parameter set has ONLY finite lower and upper bounds. } ParamHelpers/man/renderYTraces.Rd0000644000176000001440000000161413633666270016517 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/OptPath_plotYTraces.R \name{renderYTraces} \alias{renderYTraces} \title{Plots Y traces of multiple optimization paths} \usage{ renderYTraces(opt.paths, over.time = "dob") } \arguments{ \item{opt.paths}{[\code{\link[=OptPath]{OptPath()}} | list of \code{\link[=OptPath]{OptPath()}}]\cr Object(s) to plot.} \item{over.time}{\code{\link{character}}\cr Should the traces be plotted versus the iteration number or the cumulated execution time? For the later, the opt.path has to contain a extra column names exec.time. Possible values are dob and exec.time, default is \code{dob}.} } \value{ ggplot2 plot object } \description{ Can be used for only single-objective optimization paths. Useful to compare runs of different algorithms on the same optimization problem. You can add your own ggplot layers to the resulting plot object. } ParamHelpers/man/plotOptPath.Rd0000644000176000001440000000526413633666270016230 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/OptPath_plotter.R \name{plotOptPath} \alias{plotOptPath} \title{Plot method for optimization paths.} \usage{ plotOptPath( op, iters, pause = TRUE, xlim = list(), ylim = list(), title = "Optimization Path Plots", ... ) } \arguments{ \item{op}{(\code{OptPath})\cr Optimization path.} \item{iters}{(\code{integer} | NULL)\cr Vector of iterations which should be plotted one after another. If \code{NULL}, which is the default, only the last iteration is plotted. Iteration 0 plots all elements with dob = 0. Note that the plots for iteration i contains all observations alive in iteration i.} \item{pause}{(\code{logical(1)})\cr Should the process be paused after each iteration? Default is \code{TRUE}.} \item{xlim}{\link{list} \cr X axis limits for the plots. Must be a named list, so you can specify the axis limits for every plot. Every element of the list must be a numeric vector of length 2. Available names for elements are: XSpace - limits for the X-Space plot YSpace - limits for the Y-Space plot Default is an empty list - in this case limits are automatically set. Note: For some plots it is not meaningful to set limits, in this case the set limits are ignored. Note: We do not support setting lims for the over.time.plots. We think, in nearly every case the ggplot defaults are fine, and the very rare case you have to set them, you can you can extract the plots and add your own limits.} \item{ylim}{\link{list} \cr Y axis limits for the plots. Must be a named list, so you can specify the axis limits for every plot. Every element of the list must be a numeric vector of length 2. Available names for elements are: XSpace - limits for the X-Space plot YSpace - limits for the Y-Space plot Default is an empty list - in this case limits are automatically set. Note: For some plots it is not meaningful to set limits, in this case the set limits are ignored. Note: We do not support setting lims for the over.time.plots. We think, in nearly every case the ggplot defaults are fine, and the very rare case you have to set them, you can you can extract the plots and add your own limits.} \item{title}{(\code{character(1)})\cr Main title for the arranged plots, default is Optimization Path Plots.} \item{...}{Additional parameters for \code{\link[=renderOptPathPlot]{renderOptPathPlot()}}.} } \description{ Plot method for every type of optimization path, containing any numbers and types of variables. For every iteration up to 4 types of plots can be generated: One plot for the distribution of points in X and Y space respectively and plots for the trend of specified X variables, Y variables and extra measures over the time. } ParamHelpers/man/dfRowsToList.Rd0000644000176000001440000000353113633666270016350 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/dfRowsToList.R \name{dfRowsToList} \alias{dfRowsToList} \alias{dfRowToList} \title{Convert a data.frame row to list of parameter-value-lists.} \usage{ dfRowsToList(df, par.set, enforce.col.types = FALSE, ...) dfRowToList(df, par.set, i, enforce.col.types = FALSE, ...) } \arguments{ \item{df}{(\code{data.frame})\cr Data.frame, potentially from \code{\link[=OptPathDF]{OptPathDF()}}. Columns are assumed to be in the same order as par.set.} \item{par.set}{\link{ParamSet}\cr Parameter set.} \item{enforce.col.types}{(\code{logical(1)})\cr Should all \code{df} columns be initially converted to the type returned by \code{getParamTypes(df, df.cols = TRUE)}. This can help to work with \dQuote{non-standard} data.frames where the types are slightly \dQuote{off}. But note that there is no guarantee that this will work if the types are really wrong and there is no naturally correct way to convert them. Default is \code{FALSE}.} \item{...}{(any)\cr Arguments passed to \code{\link[BBmisc:convertDataFrameCols]{BBmisc::convertDataFrameCols()}}} \item{i}{(\code{integer(1)})\cr Row index.} } \value{ \code{\link{list}}. Named by parameter ids. } \description{ Please note that (naturally) the columns of \code{df} have to be of the correct type w.r.t. the corresponding parameter. The only exception are integer parameters where the corresponding columns in \code{df} are allowed to be numerics. And also see the argument \code{enforce.col.types} as a way around this restriction. \tabular{ll}{ numeric(vector) \tab \code{numeric} \cr integer(vector) \tab \code{integer} \cr discrete(vector) \tab \code{factor} (names of values = levels) \cr logical(vector) \tab \code{logical} } Dependent parameters whose requirements are not satisfied are represented by a scalar NA in the output. } ParamHelpers/man/discreteValueToName.Rd0000644000176000001440000000144713633666270017654 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/convertDiscrete.R \name{discreteValueToName} \alias{discreteValueToName} \title{Convert discrete value(s) to encoding name(s).} \usage{ discreteValueToName(par, x) } \arguments{ \item{par}{\link{Param}\cr Parameter.} \item{x}{\link{any}\cr Parameter value or a list of values for a discrete vector.} } \value{ \code{\link{character}}. Single name for a discrete parameter or a character vector of names for a discrete vector. } \description{ For a discrete parameter or discrete vector. If the value \code{x} is \code{NA}, indicating a missing parameter value due to unsatisfied requirements, \code{NA} is returned. } \examples{ p = makeDiscreteParam("u", values = c(x1 = "a", x2 = "b", x3 = "c")) discreteValueToName(p, "b") } ParamHelpers/man/getRequirements.Rd0000644000176000001440000000141313633666270017125 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/getRequirements.R \name{getRequirements} \alias{getRequirements} \title{Return all require-expressions of a param set.} \usage{ getRequirements(par.set, remove.null = TRUE) } \arguments{ \item{par.set}{\link{ParamSet}\cr Parameter set.} \item{remove.null}{(\code{logical(1)})\cr If not set, params without a requires-setting will result in a \code{NULL} element in the returned list, otherwise they are removed. Default is code{TRUE}.} } \value{ xnamed \code{list}. Named list of require-call-objects, lengths corresponds to number of params (potentially only the subset with requires-field), named with with param ids. } \description{ Returns all \code{require}s-objects of a param set as a list. } ParamHelpers/man/getParamIds.Rd0000644000176000001440000000161513633666270016146 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/getParamIds.R \name{getParamIds} \alias{getParamIds} \title{Return ids of parameters in parameter set.} \usage{ getParamIds(par, repeated = FALSE, with.nr = FALSE) } \arguments{ \item{par}{(\link{Param} | \link{ParamSet})\cr Parameter or parameter set.} \item{repeated}{(\code{logical(1)})\cr Should ids be repeated length-times if parameter is a vector? Default is \code{FALSE}.} \item{with.nr}{(\code{logical(1)})\cr Should number from 1 to length be appended to id if \code{repeated} is \code{TRUE}? Otherwise ignored. Default is \code{FALSE}.} } \value{ \code{\link{character}}. } \description{ Useful if vectors are included. } \examples{ ps = makeParamSet( makeNumericParam("u"), makeIntegerVectorParam("v", len = 2) ) getParamIds(ps) getParamIds(ps, repeated = TRUE) getParamIds(ps, repeated = TRUE, with.nr = TRUE) } ParamHelpers/man/plotYTraces.Rd0000644000176000001440000000131013633666270016207 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/OptPath_plotYTraces.R \name{plotYTraces} \alias{plotYTraces} \title{Plots Y traces of multiple optimization paths} \usage{ plotYTraces(opt.paths, over.time = "dob") } \arguments{ \item{opt.paths}{\code{\link{list}}\cr List of \code{OptPath} objects} \item{over.time}{\code{\link{character}}\cr Should the traces be plotted versus the iteration number or the cumulated execution time? For the later, the opt.path has to contain a extra column names exec.time. Possible values are dob and exec.time, default is \code{dob}.} } \value{ \code{\link{NULL}} } \description{ Plot function for \code{\link[=renderYTraces]{renderYTraces()}} } ParamHelpers/man/setOptPathElEOL.Rd0000644000176000001440000000207713633666270016665 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/OptPath_setter.R \name{setOptPathElEOL} \alias{setOptPathElEOL} \title{Set the end of life dates of parameter values, in-place.} \usage{ setOptPathElEOL(op, index, eol) } \arguments{ \item{op}{\link{OptPath}\cr Optimization path.} \item{index}{\link{integer}\cr Vector of indices of elements.} \item{eol}{\link{integer} \cr EOL dates, single value or same length of \code{index}.} } \value{ Nothing. } \description{ Set the end of life dates of parameter values, in-place. } \seealso{ Other optpath: \code{\link{OptPath}}, \code{\link{addOptPathEl}()}, \code{\link{getOptPathBestIndex}()}, \code{\link{getOptPathCols}()}, \code{\link{getOptPathCol}()}, \code{\link{getOptPathDOB}()}, \code{\link{getOptPathEOL}()}, \code{\link{getOptPathEl}()}, \code{\link{getOptPathErrorMessages}()}, \code{\link{getOptPathExecTimes}()}, \code{\link{getOptPathLength}()}, \code{\link{getOptPathParetoFront}()}, \code{\link{getOptPathX}()}, \code{\link{getOptPathY}()}, \code{\link{setOptPathElDOB}()} } \concept{optpath} ParamHelpers/man/isForbidden.Rd0000644000176000001440000000075213633666270016177 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/isForbidden.R \name{isForbidden} \alias{isForbidden} \title{Check whether parameter setting lies in forbidden region of parameter set.} \usage{ isForbidden(par.set, x) } \arguments{ \item{par.set}{\link{ParamSet}\cr Parameter set.} \item{x}{(named \code{list}) \cr Parameter setting to check.} } \value{ \code{logical(1)}. } \description{ Parameter sets without a forbidden region always return \code{FALSE}. } ParamHelpers/man/isEmpty.Rd0000644000176000001440000000052213633666270015374 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ParamSet.R \name{isEmpty} \alias{isEmpty} \title{Check whether parameter set is empty.} \usage{ isEmpty(par.set) } \arguments{ \item{par.set}{(ParamSet()])\cr Parameter set.} } \value{ \code{logical(1)}. } \description{ Check whether parameter set is empty. } ParamHelpers/man/updateParVals.Rd0000644000176000001440000000171613636350110016505 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/updateParVals.R \name{updateParVals} \alias{updateParVals} \title{Insert par.vals to old ones with meeting requirements} \usage{ updateParVals(par.set, old.par.vals, new.par.vals, warn = FALSE) } \arguments{ \item{par.set}{\link{ParamSet}\cr Parameter set.} \item{old.par.vals}{\link{list}\cr Param Values to be updated.} \item{new.par.vals}{\link{list}\cr New Param Values to update the \code{old.par.vals}.} \item{warn}{\link{logical}\cr Whether a warning should be shown, if a param setting from \code{old.par.vals} is dropped. Default is \code{FALSE}.} } \value{ \code{\link{list}}. } \description{ Update the values of a given parameter setting with a new parameter setting. Settings that do not meet the requirements anymore will be deleted from the first given parameter setting. Default values of the Param Set are respected to check if the new param settings meet the requirements. } ParamHelpers/man/LearnerParam.Rd0000644000176000001440000001241613633666270016320 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/LearnerParam.R, R/makeLearnerParamFuns.R \name{LearnerParam} \alias{LearnerParam} \alias{makeNumericLearnerParam} \alias{makeNumericVectorLearnerParam} \alias{makeIntegerLearnerParam} \alias{makeIntegerVectorLearnerParam} \alias{makeDiscreteLearnerParam} \alias{makeDiscreteVectorLearnerParam} \alias{makeLogicalLearnerParam} \alias{makeLogicalVectorLearnerParam} \alias{makeUntypedLearnerParam} \alias{makeFunctionLearnerParam} \title{Create a description object for a parameter of a machine learning algorithm.} \usage{ makeNumericLearnerParam( id, lower = -Inf, upper = Inf, allow.inf = FALSE, default, when = "train", requires = NULL, tunable = TRUE, special.vals = list() ) makeNumericVectorLearnerParam( id, len = as.integer(NA), lower = -Inf, upper = Inf, allow.inf = FALSE, default, when = "train", requires = NULL, tunable = TRUE, special.vals = list() ) makeIntegerLearnerParam( id, lower = -Inf, upper = Inf, default, when = "train", requires = NULL, tunable = TRUE, special.vals = list() ) makeIntegerVectorLearnerParam( id, len = as.integer(NA), lower = -Inf, upper = Inf, default, when = "train", requires = NULL, tunable = TRUE, special.vals = list() ) makeDiscreteLearnerParam( id, values, default, when = "train", requires = NULL, tunable = TRUE, special.vals = list() ) makeDiscreteVectorLearnerParam( id, len = as.integer(NA), values, default, when = "train", requires = NULL, tunable = TRUE, special.vals = list() ) makeLogicalLearnerParam( id, default, when = "train", requires = NULL, tunable = TRUE, special.vals = list() ) makeLogicalVectorLearnerParam( id, len = as.integer(NA), default, when = "train", requires = NULL, tunable = TRUE, special.vals = list() ) makeUntypedLearnerParam( id, default, when = "train", requires = NULL, tunable = TRUE, special.vals = list() ) makeFunctionLearnerParam( id, default, when = "train", requires = NULL, tunable = TRUE, special.vals = list() ) } \arguments{ \item{id}{(\code{character(1)})\cr Name of parameter.} \item{lower}{(\code{numeric} | \code{expression})\cr Lower bounds. A singe value of length 1 is automatically replicated to \code{len} for vector parameters. If \code{len = NA} you can only pass length-1 scalars. Default is \code{-Inf}.} \item{upper}{(\code{numeric} | \code{expression})\cr Upper bounds. A singe value of length 1 is automatically replicated to \code{len} for vector parameters. If \code{len = NA} you can only pass length-1 scalars. Default is \code{Inf}.} \item{allow.inf}{(\code{logical(1)})\cr Allow infinite values for numeric and numericvector params to be feasible settings. Default is \code{FALSE}.} \item{default}{(any concrete value | \code{expression})\cr Default value used in learner. Note: When this is a discrete parameter make sure to use a VALUE here, not the NAME of the value. If this argument is missing, it means no default value is available.} \item{when}{(\code{character(1)})\cr Specifies when parameter is used in the learner: \dQuote{train}, \dQuote{predict} or \dQuote{both}. Default is \dQuote{train}.} \item{requires}{(\code{NULL} | \code{call} | \code{expression})\cr States requirements on other parameters' values, so that setting this parameter only makes sense if its requirements are satisfied (dependent parameter). Can be an object created either with \code{expression} or \code{quote}, the former type is auto-converted into the later. Only really useful if the parameter is included in a (ParamSet()). Default is \code{NULL} which means no requirements.} \item{tunable}{(\code{logical(1)})\cr Is this parameter tunable? Defining a parameter to be not-tunable allows to mark arguments like, e.g., \dQuote{verbose} or other purely technical stuff. Note that this flag is most likely not respected by optimizing procedures unless stated otherwise. Default is \code{TRUE} (except for \code{untyped}, \code{function}, \code{character} and \code{characterVector}) which means it is tunable.} \item{special.vals}{(\code{list()})\cr A list of special values the parameter can except which are outside of the defined range. Default is an empty list.} \item{len}{(\code{integer(1)})\cr Length of vector parameter. Can be set to \code{NA} to define a vector with unspecified length.} \item{values}{(\code{vector} | \code{list} | \code{expression})\cr Possible discrete values. Instead of using a vector of atomic values, you are also allowed to pass a list of quite \dQuote{complex} R objects, which are used as discrete choices. If you do the latter, the elements must be uniquely named, so that the names can be used as internal representations for the choice.} } \value{ \code{\link[=LearnerParam]{LearnerParam()}}. } \description{ This specializes \code{\link[=Param]{Param()}} by adding a few more attributes, like a default value, whether it refers to a training or a predict function, etc. Note that you can set \code{length} to \code{NA} The S3 class is a \code{\link[=Param]{Param()}} which additionally stores these elements: \describe{ \item{when \code{character(1)}}{See argument of same name.} } See the note in \code{\link[=Param]{Param()}} about being able to pass expressions to certain arguments. } ParamHelpers/man/dropParams.Rd0000644000176000001440000000101413633666270016047 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/dropParams.R \name{dropParams} \alias{dropParams} \title{Drop Params from ParamSet by ids.} \usage{ dropParams(par.set, drop) } \arguments{ \item{par.set}{\link{ParamSet}\cr Parameter set.} \item{drop}{(\code{character})\cr \code{id}s of the \code{\link[=Param]{Param()}}s in the \code{\link[=ParamSet]{ParamSet()}} to drop from the ParamSet.} } \value{ [\code{\link[=ParamSet]{ParamSet()}}]. } \description{ Drop Params from ParamSet by ids. } ParamHelpers/man/getLower.Rd0000644000176000001440000000420013633666270015527 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/getBounds.R \name{getLower} \alias{getLower} \alias{getUpper} \alias{getValues} \title{Get lower / upper bounds and allowed discrete values for parameters.} \usage{ getLower(obj, with.nr = FALSE, dict = NULL) getUpper(obj, with.nr = FALSE, dict = NULL) getValues(obj, dict = NULL) } \arguments{ \item{obj}{(\code{\link[=Param]{Param()}} | \code{\link[=ParamSet]{ParamSet()}} | \code{list})\cr Parameter, parameter set or list of parameters, whose boundaries and/or values should be extracted. In case the boundaries or values contain expressions, they will be evaluated using the provided dictionary \code{dict}.} \item{with.nr}{(\code{logical(1)})\cr Should number from 1 to length be appended to names of vector params? Default is \code{FALSE}.} \item{dict}{(\code{environment} | \link{list} | \code{NULL})\cr Environment or list which will be used for evaluating the variables of expressions within a parameter, parameter set or list of parameters. The default is \code{NULL}.} } \value{ \code{vector} | \code{list}. Named by parameter ids. } \description{ \code{getLower} and \code{getUpper} return a numerical vector of lower and upper bounds, \code{getValues} returns a list of possible value sets for discrete parameters. Parameters for which such bound make no sense - due to their type - are not present in the result. } \examples{ ps = makeParamSet( makeNumericParam("u"), makeDiscreteParam("v", values = c("a", "b")), makeIntegerParam("w", lower = expression(ceiling(p / 3)), upper = 2), makeDiscreteParam("x", values = 1:2), makeNumericVectorParam("y", len = 2, lower = c(0, 10), upper = c(1, 11)), keys = "p" ) getLower(ps, dict = list(p = 7)) getUpper(ps) ps = makeParamSet( makeNumericParam("u"), makeDiscreteParam("w", values = list(a = list(), b = NULL)) ) getValues(ps) par.vals = list( u = makeNumericParam("u"), v = makeIntegerParam("v", lower = 1, upper = 2), w = makeDiscreteParam("w", values = 1:2), x = makeNumericVectorParam("x", len = 2, lower = c(3, 1), upper = expression(n)) ) getLower(par.vals) getUpper(par.vals, dict = list(n = 12)) } ParamHelpers/man/isSpecialValue.Rd0000644000176000001440000000061213633666270016653 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/isSpecialValue.R \name{isSpecialValue} \alias{isSpecialValue} \title{Is a given value in the list of special values for a param?} \usage{ isSpecialValue(par, x) } \arguments{ \item{par}{\link{Param}\cr Parameter.} \item{x}{(any) \cr Single value to check.} } \value{ \code{logical(1)}. } \description{ See title. } ParamHelpers/man/getOptPathCol.Rd0000644000176000001440000000246513633666270016467 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/OptPath_getter.R \name{getOptPathCol} \alias{getOptPathCol} \title{Get column from the optimization path.} \usage{ getOptPathCol(op, name, dob, eol) } \arguments{ \item{op}{\link{OptPath}\cr Optimization path.} \item{name}{(\code{character(1)})\cr Name of the column.} \item{dob}{\link{integer}\cr Vector of date-of-birth values to further subset the result. Only elements with a date-of-birth included in \code{dob} are selected. Default is all.} \item{eol}{\link{integer}\cr Vector of end-of-life values to further subset the result. Only elements with an end-of-life included in \code{eol} are selected. Default is all.} } \value{ Single column as a vector. } \description{ Get column from the optimization path. } \seealso{ Other optpath: \code{\link{OptPath}}, \code{\link{addOptPathEl}()}, \code{\link{getOptPathBestIndex}()}, \code{\link{getOptPathCols}()}, \code{\link{getOptPathDOB}()}, \code{\link{getOptPathEOL}()}, \code{\link{getOptPathEl}()}, \code{\link{getOptPathErrorMessages}()}, \code{\link{getOptPathExecTimes}()}, \code{\link{getOptPathLength}()}, \code{\link{getOptPathParetoFront}()}, \code{\link{getOptPathX}()}, \code{\link{getOptPathY}()}, \code{\link{setOptPathElDOB}()}, \code{\link{setOptPathElEOL}()} } \concept{optpath} ParamHelpers/man/getParamTypes.Rd0000644000176000001440000000237413633666270016536 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/getParamTypes.R \name{getParamTypes} \alias{getParamTypes} \title{Returns type information for a parameter set.} \usage{ getParamTypes( par.set, df.cols = FALSE, df.discretes.as.factor = TRUE, use.names = FALSE, with.nr = TRUE ) } \arguments{ \item{par.set}{\link{ParamSet}\cr Parameter set.} \item{df.cols}{(\code{logical(1)})\cr If \code{FALSE} simply return the parameter types in the set, i.e., \code{par$type}. If \code{TRUE}, convert types so they correspond to R types of a data.frame where values of this set might be stored. This also results in replication of output types for vector parameters. Default is \code{FALSE}.} \item{df.discretes.as.factor}{(\code{logical(1)})\cr If \code{df.cols} is \code{TRUE}: Should type for discrete params be \code{factor} or \code{character}? Default is \code{TRUE}.} \item{use.names}{(\code{logical(1)})\cr Name the result vector? Default is \code{FALSE}.} \item{with.nr}{(\code{logical(1)})\cr Should number from 1 to length be appended to name? Only used if \code{use.names} and \code{df.cols} are \code{TRUE}. Default is \code{TRUE}.} } \value{ \code{\link{character}}. } \description{ Returns type information for a parameter set. } ParamHelpers/man/hasExpression.Rd0000644000176000001440000000151313633666270016576 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/hasExpression.R \name{hasExpression} \alias{hasExpression} \title{Check if parameter values contain expressions.} \usage{ hasExpression(obj) } \arguments{ \item{obj}{(\code{\link[=Param]{Param()}} | \code{\link[ParamHelpers:ParamSet]{ParamHelpers::ParamSet()}} | \code{list})\cr Parameter, parameter set or list of parameters.} } \value{ \code{logical(1)}. } \description{ Checks if a parameter, parameter set or list of parameters contain expressions. } \examples{ ps1 = makeParamSet( makeNumericParam("x", lower = 1, upper = 2), makeNumericParam("y", lower = 1, upper = 10) ) ps2 = makeParamSet( makeNumericLearnerParam("x", lower = 1, upper = 2), makeNumericLearnerParam("y", lower = 1, upper = expression(p)) ) hasExpression(ps1) hasExpression(ps2) } ParamHelpers/man/getOptPathY.Rd0000644000176000001440000000310313633666270016150 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/OptPath_getter.R \name{getOptPathY} \alias{getOptPathY} \title{Get y-vector or y-matrix from the optimization path.} \usage{ getOptPathY(op, names, dob, eol, drop = TRUE) } \arguments{ \item{op}{\link{OptPath}\cr Optimization path.} \item{names}{\link{character}\cr Names of performance measure. Default is all performance measures in path.} \item{dob}{\link{integer}\cr Vector of date-of-birth values to further subset the result. Only elements with a date-of-birth included in \code{dob} are selected. Default is all.} \item{eol}{\link{integer}\cr Vector of end-of-life values to further subset the result. Only elements with an end-of-life included in \code{eol} are selected. Default is all.} \item{drop}{(\code{logical(1)})\cr Return vector instead of matrix when only one y-column was selected? Default is \code{TRUE}.} } \value{ (\code{numeric} | \code{matrix}). The columns of the matrix are always named. } \description{ Get y-vector or y-matrix from the optimization path. } \seealso{ Other optpath: \code{\link{OptPath}}, \code{\link{addOptPathEl}()}, \code{\link{getOptPathBestIndex}()}, \code{\link{getOptPathCols}()}, \code{\link{getOptPathCol}()}, \code{\link{getOptPathDOB}()}, \code{\link{getOptPathEOL}()}, \code{\link{getOptPathEl}()}, \code{\link{getOptPathErrorMessages}()}, \code{\link{getOptPathExecTimes}()}, \code{\link{getOptPathLength}()}, \code{\link{getOptPathParetoFront}()}, \code{\link{getOptPathX}()}, \code{\link{setOptPathElDOB}()}, \code{\link{setOptPathElEOL}()} } \concept{optpath} ParamHelpers/man/hasTrafo.Rd0000644000176000001440000000064213633666270015514 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/hasTrafo.R \name{hasTrafo} \alias{hasTrafo} \title{Check parameter / parameter set for trafos.} \usage{ hasTrafo(par) } \arguments{ \item{par}{(\link{Param} | \link{ParamSet})\cr Parameter or parameter set.} } \value{ \code{logical(1)}. } \description{ \code{TRUE} iff the parameter has any trafos or any parameter in the set has trafos. } ParamHelpers/man/hasRequires.Rd0000644000176000001440000000071713633666270016243 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/hasRequires.R \name{hasRequires} \alias{hasRequires} \title{Check parameter / parameter set for requirements / dependencies.} \usage{ hasRequires(par) } \arguments{ \item{par}{(\link{Param} | \link{ParamSet})\cr Parameter or parameter set.} } \value{ \code{logical(1)}. } \description{ \code{TRUE} iff the parameter has any requirements or any parameter in the set has requirements. } ParamHelpers/man/convertParamSetToIrace.Rd0000644000176000001440000000136413633666270020333 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/convertParamSetToIrace.R \name{convertParamSetToIrace} \alias{convertParamSetToIrace} \title{Converts a ParamSet object to a parameter object of the irace package.} \usage{ convertParamSetToIrace(par.set, as.chars = FALSE) } \arguments{ \item{par.set}{\link{ParamSet}\cr Parameter set.} \item{as.chars}{(\code{logical(1)})\cr Return results as character vector of lines \code{FALSE} or call \code{\link[irace:readParameters]{irace::readParameters()}} on it (\code{TRUE}). Default is \code{FALSE}.} } \value{ [\code{\link[=list]{list()}}]. } \description{ Converts to a textual description used in irace and then potentially calls \link[irace:readParameters]{readParameters}. } ParamHelpers/man/generateDesign.Rd0000644000176000001440000001132613633666270016672 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/generateDesign.R \name{generateDesign} \alias{generateDesign} \title{Generates a statistical design for a parameter set.} \usage{ generateDesign( n = 10L, par.set, fun, fun.args = list(), trafo = FALSE, augment = 20L ) } \arguments{ \item{n}{(\code{integer(1)})\cr Number of samples in design. Default is 10.} \item{par.set}{\link{ParamSet}\cr Parameter set.} \item{fun}{(\code{function})\cr Function from package lhs. Possible are: \code{\link[lhs:maximinLHS]{lhs::maximinLHS()}}, \code{\link[lhs:randomLHS]{lhs::randomLHS()}}, \code{\link[lhs:geneticLHS]{lhs::geneticLHS()}}, \code{\link[lhs:improvedLHS]{lhs::improvedLHS()}}, \code{\link[lhs:optAugmentLHS]{lhs::optAugmentLHS()}}, \code{\link[lhs:optimumLHS]{lhs::optimumLHS()}} Default is \code{\link[lhs:randomLHS]{lhs::randomLHS()}}.} \item{fun.args}{(\code{list})\cr List of further arguments passed to \code{fun}.} \item{trafo}{(\code{logical(1)})\cr Transform all parameters by using theirs respective transformation functions. Default is \code{FALSE}.} \item{augment}{(\code{integer(1)})\cr Duplicated values and forbidden regions in the parameter space can lead to the design becoming smaller than \code{n}. With this option it is possible to augment the design again to size \code{n}. It is not guaranteed that this always works (to full size) and \code{augment} specifies the number of tries to augment. If the the design is of size less than \code{n} after all tries, a warning is issued and the smaller design is returned. Default is 20.} } \value{ \link{data.frame}. Columns are named by the ids of the parameters. If the \code{par.set} argument contains a vector parameter, its corresponding column names in the design are the parameter id concatenated with 1 to dimension of the vector. The result will have an \code{logical(1)} attribute \dQuote{trafo}, which is set to the value of argument \code{trafo}. } \description{ The following types of columns are created: \tabular{ll}{ numeric(vector) \tab \code{numeric} \cr integer(vector) \tab \code{integer} \cr discrete(vector) \tab \code{factor} (names of values = levels) \cr logical(vector) \tab \code{logical} } If you want to convert these, look at \code{\link[BBmisc:convertDataFrameCols]{BBmisc::convertDataFrameCols()}}. Dependent parameters whose constraints are unsatisfied generate \code{NA} entries in their respective columns. For discrete vectors the levels and their order will be preserved, even if not all levels are present. Currently only lhs designs are supported. The algorithm currently iterates the following steps: \enumerate{ \item{We create a space filling design for all parameters, disregarding \code{requires}, a \code{trafo} or the forbidden region.} \item{Forbidden points are removed.} \item{Parameters are trafoed (potentially, depending on the setting of argument \code{trafo}); dependent parameters whose constraints are unsatisfied are set to \code{NA} entries.} \item{Duplicated design points are removed. Duplicated points are not generated in a reasonable space-filling design, but the way discrete parameters and also parameter dependencies are handled make this possible.} \item{If we removed some points, we now try to augment the design in a space-filling way and iterate.} } Note that augmenting currently is somewhat experimental as we simply generate missing points via new calls to \code{\link[lhs:randomLHS]{lhs::randomLHS()}}, but do not add points so they are maximally far away from the already present ones. The reason is that the latter is quite hard to achieve with complicated dependencies and forbidden regions, if one wants to ensure that points actually get added... But we are working on it. Note that if you have trafos attached to your params, the complete creation of the design (except for the detection of invalid parameters w.r.t to their \code{requires} setting) takes place on the UNTRANSFORMED scale. So this function creates, e.g., a maximin LHS design on the UNTRANSFORMED scale, but not necessarily the transformed scale. \code{generateDesign} will NOT work if there are dependencies over multiple levels of parameters and the dependency is only given with respect to the \dQuote{previous} parameter. A current workaround is to state all dependencies on all parameters involved. (We are working on it.) } \examples{ ps = makeParamSet( makeNumericParam("x1", lower = -2, upper = 1), makeIntegerParam("x2", lower = 10, upper = 20) ) # random latin hypercube design with 5 samples: generateDesign(5, ps) # with trafo ps = makeParamSet( makeNumericParam("x", lower = -2, upper = 1), makeNumericVectorParam("y", len = 2, lower = 0, upper = 1, trafo = function(x) x / sum(x)) ) generateDesign(10, ps, trafo = TRUE) } ParamHelpers/man/getOptPathExecTimes.Rd0000644000176000001440000000241113633666270017627 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/OptPath_getter.R \name{getOptPathExecTimes} \alias{getOptPathExecTimes} \title{Get exec-time vector from the optimization path.} \usage{ getOptPathExecTimes(op, dob, eol) } \arguments{ \item{op}{\link{OptPath}\cr Optimization path.} \item{dob}{\link{integer}\cr Vector of date-of-birth values to further subset the result. Only elements with a date-of-birth included in \code{dob} are selected. Default is all.} \item{eol}{\link{integer}\cr Vector of end-of-life values to further subset the result. Only elements with an end-of-life included in \code{eol} are selected. Default is all.} } \value{ \link{numeric}. } \description{ Get exec-time vector from the optimization path. } \seealso{ Other optpath: \code{\link{OptPath}}, \code{\link{addOptPathEl}()}, \code{\link{getOptPathBestIndex}()}, \code{\link{getOptPathCols}()}, \code{\link{getOptPathCol}()}, \code{\link{getOptPathDOB}()}, \code{\link{getOptPathEOL}()}, \code{\link{getOptPathEl}()}, \code{\link{getOptPathErrorMessages}()}, \code{\link{getOptPathLength}()}, \code{\link{getOptPathParetoFront}()}, \code{\link{getOptPathX}()}, \code{\link{getOptPathY}()}, \code{\link{setOptPathElDOB}()}, \code{\link{setOptPathElEOL}()} } \concept{optpath} ParamHelpers/man/setValueCNames.Rd0000644000176000001440000000106013633666270016617 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/setValueCNames.R \name{setValueCNames} \alias{setValueCNames} \title{Set components names for vector names} \usage{ setValueCNames(par, x) } \arguments{ \item{par}{(\link{Param} | \link{ParamSet})\cr Parameter or parameter set.} \item{x}{(any) \cr Param value(s). For a parameter set this must be a list in the correct order.} } \value{ \code{x} with changed names. } \description{ If param has \code{cnames} set component names in a value. Otherwise \code{x} is left unchanged. } ParamHelpers/man/setOptPathElDOB.Rd0000644000176000001440000000207613633666270016651 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/OptPath_setter.R \name{setOptPathElDOB} \alias{setOptPathElDOB} \title{Set the dates of birth of parameter values, in-place.} \usage{ setOptPathElDOB(op, index, dob) } \arguments{ \item{op}{\link{OptPath}\cr Optimization path.} \item{index}{\link{integer}\cr Vector of indices of elements.} \item{dob}{\link{integer} \cr Dates of birth, single value or same length of \code{index}.} } \value{ Nothing. } \description{ Set the dates of birth of parameter values, in-place. } \seealso{ Other optpath: \code{\link{OptPath}}, \code{\link{addOptPathEl}()}, \code{\link{getOptPathBestIndex}()}, \code{\link{getOptPathCols}()}, \code{\link{getOptPathCol}()}, \code{\link{getOptPathDOB}()}, \code{\link{getOptPathEOL}()}, \code{\link{getOptPathEl}()}, \code{\link{getOptPathErrorMessages}()}, \code{\link{getOptPathExecTimes}()}, \code{\link{getOptPathLength}()}, \code{\link{getOptPathParetoFront}()}, \code{\link{getOptPathX}()}, \code{\link{getOptPathY}()}, \code{\link{setOptPathElEOL}()} } \concept{optpath} ParamHelpers/man/getTypeStrings.Rd0000644000176000001440000000174213633666270016742 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/getTypeStrings.R \name{getTypeStrings} \alias{getTypeStrings} \alias{getTypeStringsAll} \alias{getTypeStringsNumeric} \alias{getTypeStringsNumericStrict} \alias{getTypeStringsInteger} \alias{getTypeStringsCharacter} \alias{getTypeStringsDiscrete} \alias{getTypeStringsLogical} \title{Get parameter type-strings.} \usage{ getTypeStringsAll() getTypeStringsNumeric(include.int = TRUE) getTypeStringsNumericStrict() getTypeStringsInteger() getTypeStringsCharacter() getTypeStringsDiscrete(include.logical = TRUE) getTypeStringsLogical() } \arguments{ \item{include.int}{(\code{logical(1)})\cr Are integers also considered to be numeric? Default is \code{TRUE}.} \item{include.logical}{(\code{logical(1)})\cr Are logicals also considered to be discrete? Default is \code{TRUE}.} } \value{ \code{\link{character}}. } \description{ Returns type strings used in \code{param$type} for certain groups of parameters. } ParamHelpers/man/isVector.Rd0000644000176000001440000000067313633666270015547 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/isVector.R \name{isVector} \alias{isVector} \title{Check parameter / parameter set for vector params.} \usage{ isVector(par) } \arguments{ \item{par}{(\link{Param} | \link{ParamSet})\cr Parameter or parameter set.} } \value{ \code{logical(1)}. } \description{ \code{TRUE} if the parameter is a vector parameter or all parameters in the set are vector parameters. } ParamHelpers/man/hasType.Rd0000644000176000001440000000161113633666270015357 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/hasType.R \name{hasType} \alias{hasType} \alias{hasDiscrete} \alias{hasInteger} \alias{hasLogical} \alias{hasCharacter} \alias{hasNumeric} \title{Check whether parameter set contains a certain type.} \usage{ hasDiscrete(par.set, include.logical = TRUE) hasInteger(par.set) hasLogical(par.set) hasCharacter(par.set) hasNumeric(par.set, include.int = TRUE) } \arguments{ \item{par.set}{\link{ParamSet}\cr Parameter set.} \item{include.logical}{(\code{logical(1)})\cr Are logicals also considered to be discrete? Default is \code{TRUE}.} \item{include.int}{(\code{logical(1)})\cr Are integers also considered to be numeric? Default is \code{TRUE}.} } \value{ \code{logical(1)} } \description{ \code{TRUE} if the parameter set contains at least one parameter of the mentioned type x. Type x always subsumes x and x-vector. } ParamHelpers/man/as.data.frame.OptPathDF.Rd0000644000176000001440000000424013633666270020137 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/OptPathDF_as_data_frame.R \name{as.data.frame.OptPathDF} \alias{as.data.frame.OptPathDF} \title{Convert optimization path to data.frame.} \usage{ \method{as.data.frame}{OptPathDF}( x, row.names = NULL, optional = FALSE, include.x = TRUE, include.y = TRUE, include.rest = TRUE, dob = x$env$dob, eol = x$env$eol, ... ) } \arguments{ \item{x}{(\code{\link[=OptPath]{OptPath()}})\cr Optimization path.} \item{row.names}{\link{character}\cr Row names for result. Default is none.} \item{optional}{(any)\cr Currently ignored.} \item{include.x}{(\code{logical(1)})\cr Include all input params? Default is \code{TRUE}.} \item{include.y}{(\code{logical(1)})\cr Include all y-columns? Default is \code{TRUE}.} \item{include.rest}{(\code{logical(1)})\cr Include all other columns? Default is \code{TRUE}.} \item{dob}{\link{integer}\cr Vector of date-of-birth values to further subset the result. Only elements with a date-of-birth included in \code{dob} are selected. Default is all.} \item{eol}{\link{integer}\cr Vector of end-of-life values to further subset the result. Only elements with an end-of-life included in \code{eol} are selected. Default is all.} \item{...}{(any) \cr Currently ignored.} } \value{ \code{\link{data.frame}}. } \description{ The following types of columns are created: \tabular{ll}{ x-numeric(vector) \tab \code{numeric} \cr x-integer(vector) \tab \code{integer} \cr x-discrete(vector) \tab \code{factor} (names of values = levels) \cr x-logical(vector) \tab \code{logical} \cr y-columns \tab \code{numeric} \cr dob \tab \code{integer} \cr eol \tab \code{integer} \cr error.message \tab \code{character} \cr exec.time \tab \code{numeric} \cr extra-columns \tab any \cr } If you want to convert these, look at \code{\link[BBmisc:convertDataFrameCols]{BBmisc::convertDataFrameCols()}}. Dependent parameters whose constraints are unsatisfied generate \code{NA} entries in their respective columns. Factor columns of discrete parameters always have their complete level set from the \code{param.set}. } ParamHelpers/man/getParamTypeCounts.Rd0000644000176000001440000000105413633666270017541 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/getParamTypeCounts.R \name{getParamTypeCounts} \alias{getParamTypeCounts} \title{Returns information on the number of parameters of a each type.} \usage{ getParamTypeCounts(par.set) } \arguments{ \item{par.set}{\link{ParamSet}\cr Parameter set.} } \value{ \code{\link{list}} Named list which contains for each supported parameter type the number of parameters of this type in the given ParamSet. } \description{ Returns information on the number of parameters of a each type. } ParamHelpers/man/sampleValues.Rd0000644000176000001440000000246413636350110016374 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/sample.R \name{sampleValues} \alias{sampleValues} \title{Sample n random values from a parameter or a parameter set uniformly.} \usage{ sampleValues(par, n, discrete.names = FALSE, trafo = FALSE) } \arguments{ \item{par}{(\link{Param} | \link{ParamSet})\cr Parameter or parameter set.} \item{n}{(\code{integer(1)})\cr Number of values.} \item{discrete.names}{(\code{logical(1)})\cr Should names be sampled for discrete parameters or values instead? Default is code {FALSE}.} \item{trafo}{(\code{logical(1)})\cr Transform all parameters by using theirs respective transformation functions. Default is \code{FALSE}.} } \value{ \code{list}. For consistency always a list is returned. } \description{ Sample n random values from a parameter or a parameter set uniformly. Dependent parameters whose requirements are not satisfied are represented by a scalar NA in the output. } \examples{ p = makeIntegerParam("x", lower = -10, upper = 10) sampleValues(p, 4) p = makeNumericParam("x", lower = -10, upper = 10) sampleValues(p, 4) p = makeLogicalParam("x") sampleValues(p, 4) ps = makeParamSet( makeNumericParam("u", lower = 1, upper = 10), makeIntegerParam("v", lower = 1, upper = 10), makeDiscreteParam("w", values = 1:2) ) sampleValues(ps, 2) } ParamHelpers/man/getParamSet.Rd0000644000176000001440000000071113633666270016156 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/getParamSet.R \name{getParamSet} \alias{getParamSet} \title{Get parameter set.} \usage{ getParamSet(x) } \arguments{ \item{x}{(\code{object}) \cr Object to extract the ParamSet from.} } \value{ \code{\link[ParamHelpers:ParamSet]{ParamHelpers::ParamSet()}} } \description{ \code{getParamSet} is a generic and can be called to extract the \code{ParamSet} from different objects. } ParamHelpers/man/getOptPathEl.Rd0000644000176000001440000000256513633666270016313 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/OptPath_getter.R \name{getOptPathEl} \alias{getOptPathEl} \title{Get an element from the optimization path.} \usage{ getOptPathEl(op, index) } \arguments{ \item{op}{\link{OptPath}\cr Optimization path.} \item{index}{(\code{integer(1)})\cr Index of element.} } \value{ List with elements \code{x} (named \code{list}), \code{y} (named \code{numeric}), \code{dob} \code{integer(1)}, \code{eol} \code{integer(1)}. The elements \code{error.message} (\code{character(1)}), \code{exec.time} (\code{numeric(1)}) and \code{extra} (named \code{list}) are there if the respective options in \code{\link[=OptPath]{OptPath()}} are enabled. } \description{ Dependent parameters whose requirements are not satisfied are represented by a scalar NA in the elements of \code{x} of the return value. } \seealso{ Other optpath: \code{\link{OptPath}}, \code{\link{addOptPathEl}()}, \code{\link{getOptPathBestIndex}()}, \code{\link{getOptPathCols}()}, \code{\link{getOptPathCol}()}, \code{\link{getOptPathDOB}()}, \code{\link{getOptPathEOL}()}, \code{\link{getOptPathErrorMessages}()}, \code{\link{getOptPathExecTimes}()}, \code{\link{getOptPathLength}()}, \code{\link{getOptPathParetoFront}()}, \code{\link{getOptPathX}()}, \code{\link{getOptPathY}()}, \code{\link{setOptPathElDOB}()}, \code{\link{setOptPathElEOL}()} } \concept{optpath} ParamHelpers/man/Param.Rd0000644000176000001440000001600113633666270015001 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/aParam.R, R/makeParamFuns.R \name{Param} \alias{Param} \alias{makeNumericParam} \alias{makeNumericVectorParam} \alias{makeIntegerParam} \alias{makeIntegerVectorParam} \alias{makeLogicalParam} \alias{makeLogicalVectorParam} \alias{makeDiscreteParam} \alias{makeDiscreteVectorParam} \alias{makeFunctionParam} \alias{makeUntypedParam} \alias{makeCharacterParam} \alias{makeCharacterVectorParam} \title{Create a description object for a parameter.} \usage{ makeNumericParam( id, lower = -Inf, upper = Inf, allow.inf = FALSE, default, trafo = NULL, requires = NULL, tunable = TRUE, special.vals = list() ) makeNumericVectorParam( id, len, lower = -Inf, upper = Inf, cnames = NULL, allow.inf = FALSE, default, trafo = NULL, requires = NULL, tunable = TRUE, special.vals = list() ) makeIntegerParam( id, lower = -Inf, upper = Inf, default, trafo = NULL, requires = NULL, tunable = TRUE, special.vals = list() ) makeIntegerVectorParam( id, len, lower = -Inf, upper = Inf, cnames = NULL, default, trafo = NULL, requires = NULL, tunable = TRUE, special.vals = list() ) makeLogicalParam( id, default, requires = NULL, tunable = TRUE, special.vals = list() ) makeLogicalVectorParam( id, len, cnames = NULL, default, requires = NULL, tunable = TRUE, special.vals = list() ) makeDiscreteParam( id, values, trafo = NULL, default, requires = NULL, tunable = TRUE, special.vals = list() ) makeDiscreteVectorParam( id, len, values, trafo = NULL, default, requires = NULL, tunable = TRUE, special.vals = list() ) makeFunctionParam( id, default = default, requires = NULL, special.vals = list() ) makeUntypedParam( id, default, requires = NULL, tunable = TRUE, special.vals = list() ) makeCharacterParam(id, default, requires = NULL, special.vals = list()) makeCharacterVectorParam( id, len, cnames = NULL, default, requires = NULL, special.vals = list() ) } \arguments{ \item{id}{(\code{character(1)})\cr Name of parameter.} \item{lower}{(\code{numeric} | \code{expression})\cr Lower bounds. A singe value of length 1 is automatically replicated to \code{len} for vector parameters. If \code{len = NA} you can only pass length-1 scalars. Default is \code{-Inf}.} \item{upper}{(\code{numeric} | \code{expression})\cr Upper bounds. A singe value of length 1 is automatically replicated to \code{len} for vector parameters. If \code{len = NA} you can only pass length-1 scalars. Default is \code{Inf}.} \item{allow.inf}{(\code{logical(1)})\cr Allow infinite values for numeric and numericvector params to be feasible settings. Default is \code{FALSE}.} \item{default}{(any concrete value | \code{expression})\cr Default value used in learner. Note: When this is a discrete parameter make sure to use a VALUE here, not the NAME of the value. If this argument is missing, it means no default value is available.} \item{trafo}{(\code{NULL} | \verb{function(x)})\cr Function to transform parameter. It should be applied to the parameter value before it is, e.g., passed to a corresponding objective function. Function must accept a parameter value as the first argument and return a transformed one. Default is \code{NULL} which means no transformation.} \item{requires}{(\code{NULL} | \code{call} | \code{expression})\cr States requirements on other parameters' values, so that setting this parameter only makes sense if its requirements are satisfied (dependent parameter). Can be an object created either with \code{expression} or \code{quote}, the former type is auto-converted into the later. Only really useful if the parameter is included in a (ParamSet()). Default is \code{NULL} which means no requirements.} \item{tunable}{(\code{logical(1)})\cr Is this parameter tunable? Defining a parameter to be not-tunable allows to mark arguments like, e.g., \dQuote{verbose} or other purely technical stuff. Note that this flag is most likely not respected by optimizing procedures unless stated otherwise. Default is \code{TRUE} (except for \code{untyped}, \code{function}, \code{character} and \code{characterVector}) which means it is tunable.} \item{special.vals}{(\code{list()})\cr A list of special values the parameter can except which are outside of the defined range. Default is an empty list.} \item{len}{(\code{integer(1)} | \code{expression})\cr Length of vector parameter.} \item{cnames}{(\code{character})\cr Component names for vector params (except discrete). Every function in this package that creates vector values for such a param, will name that vector with \code{cnames}.} \item{values}{(\code{vector} | \code{list} | \code{expression})\cr Possible discrete values. Instead of using a vector of atomic values, you are also allowed to pass a list of quite \dQuote{complex} R objects, which are used as discrete choices. If you do the latter, the elements must be uniquely named, so that the names can be used as internal representations for the choice.} } \value{ [\code{\link[=Param]{Param()}}]. } \description{ For each parameter type a special constructor function is available, see below. For the following arguments you can also pass an \code{expression} instead of a concrete value: \code{default}, \code{len}, \code{lower}, \code{upper}, \code{values}. These expressions can depend on arbitrary symbols, which are later filled in / substituted from a dictionary, in order to produce a concrete valu, see \code{\link[=evaluateParamExpressions]{evaluateParamExpressions()}}. So this enables data / context dependent settings, which is sometimes useful. The S3 class is a list which stores these elements: \describe{ \item{id (\code{character(1)})}{See argument of same name.} \item{type (\code{character(1)})}{Data type of parameter. For all type string see (getTypeStringsAll())} \item{len (\code{integer(1)} | \code{expression})}{See argument of same name.} \item{lower (\code{numeric} | \code{expression})}{See argument of same name. Length of this vector is \code{len}.} \item{upper (\code{numeric} | \code{expression})}{See argument of same name. Length of this vector is \code{len}.} \item{values (\code{list} | \code{expression})}{Discrete values, always stored as a named list.} \item{cnames (\code{character}}{See argument of same name.} \item{allow.inf (\code{logical(1)})}{See argument of same name.} \item{trafo (\code{NULL} | \verb{function(x)})}{See argument of same name.} \item{requires (\code{NULL} | \code{expression})}{See argument of same name.} \item{default (any concrete value | \code{expression})}{See argument of same name.} \item{has.default (\code{logical(1)})}{Extra flag to really be able to check whether the user passed a default, to avoid troubles with \code{NULL} and \code{NA}.} \item{tunable (\code{logical(1)})}{See argument of same name.} \item{special.vals (\code{list})}{See argument of same name.} } } \examples{ makeNumericParam("x", lower = -1, upper = 1) makeNumericVectorParam("x", len = 2) makeDiscreteParam("y", values = c("a", "b")) makeCharacterParam("z") } ParamHelpers/man/isType.Rd0000644000176000001440000000150013633666270015214 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/isType.R \name{isType} \alias{isType} \alias{isNumeric} \alias{isDiscrete} \alias{isInteger} \alias{isLogical} \alias{isCharacter} \title{Check parameter / parameter set contain ONLY a certain type.} \usage{ isNumeric(par, include.int = TRUE) isDiscrete(par, include.logical = TRUE) isInteger(par) isLogical(par) isCharacter(par) } \arguments{ \item{par}{(\link{Param} | \link{ParamSet})\cr Parameter or parameter set.} \item{include.int}{(\code{logical(1)})\cr Are integers also considered to be numeric? Default is \code{TRUE}.} \item{include.logical}{(\code{logical(1)})\cr Are logicals also considered to be discrete? Default is \code{TRUE}.} } \value{ (\code{logical(1)}) } \description{ An empty param set is considered to be of all types. } ParamHelpers/man/isRequiresOk.Rd0000644000176000001440000000164113633666270016372 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/isRequiresOk.R \name{isRequiresOk} \alias{isRequiresOk} \title{Check if parameter requirements are met.} \usage{ isRequiresOk(par.set, par.vals, ids = names(par.vals), use.defaults = TRUE) } \arguments{ \item{par.set}{\link{ParamSet}\cr Parameter set.} \item{par.vals}{(\code{list()}) \cr List of parameter settings.} \item{ids}{(\code{character()}) \cr \code{id}s of the param.vals to check. Default is \code{names(par.vals)}.} \item{use.defaults}{(\code{logical()}) \cr Some requirements relay on default values of the \code{par.set}. Default is \code{TRUE}, which means that if the value is not present in \code{par.vals} the default value will be considered.} } \value{ \code{logical(1)} \cr } \description{ Check if a parameter value satisfies the requirements of the parameter description. This only checks the \code{requires} expressions. } ParamHelpers/man/getOptPathEOL.Rd0000644000176000001440000000240113633666270016357 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/OptPath_getter.R \name{getOptPathEOL} \alias{getOptPathEOL} \title{Get end-of-life vector from the optimization path.} \usage{ getOptPathEOL(op, dob, eol) } \arguments{ \item{op}{\link{OptPath}\cr Optimization path.} \item{dob}{\link{integer}\cr Vector of date-of-birth values to further subset the result. Only elements with a date-of-birth included in \code{dob} are selected. Default is all.} \item{eol}{\link{integer}\cr Vector of end-of-life values to further subset the result. Only elements with an end-of-life included in \code{eol} are selected. Default is all.} } \value{ \link{integer}. } \description{ Get end-of-life vector from the optimization path. } \seealso{ Other optpath: \code{\link{OptPath}}, \code{\link{addOptPathEl}()}, \code{\link{getOptPathBestIndex}()}, \code{\link{getOptPathCols}()}, \code{\link{getOptPathCol}()}, \code{\link{getOptPathDOB}()}, \code{\link{getOptPathEl}()}, \code{\link{getOptPathErrorMessages}()}, \code{\link{getOptPathExecTimes}()}, \code{\link{getOptPathLength}()}, \code{\link{getOptPathParetoFront}()}, \code{\link{getOptPathX}()}, \code{\link{getOptPathY}()}, \code{\link{setOptPathElDOB}()}, \code{\link{setOptPathElEOL}()} } \concept{optpath} ParamHelpers/man/addOptPathEl.Rd0000644000176000001440000000554113633666270016261 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/OptPath_setter.R \name{addOptPathEl} \alias{addOptPathEl} \title{Add a new element to an optimization path.} \usage{ addOptPathEl( op, x, y, dob = getOptPathLength(op) + 1L, eol = as.integer(NA), error.message = NA_character_, exec.time = NA_real_, extra = NULL, check.feasible = !op$add.transformed.x ) } \arguments{ \item{op}{\link{OptPath}\cr Optimization path.} \item{x}{(\code{list})\cr List of parameter values for a point in input space. Must be in same order as parameters.} \item{y}{(\code{numeric})\cr Vector of fitness values. Must be in same order as \code{y.names}.} \item{dob}{(\code{integer(1)})\cr Date of birth of the new parameters. Default is length of path + 1.} \item{eol}{(\code{integer(1)})\cr End of life of point. Default is \code{NA}.} \item{error.message}{(\code{character(1)})\cr Possible error message that occurred for this parameter values. Default is \code{NA}.} \item{exec.time}{(\code{numeric(1)})\cr Possible exec time for this evaluation. Default is \code{NA}.} \item{extra}{(\code{list})\cr Possible list of extra values to store. The list must be fully named. The list can contain nonscalar values, but these nonscalar entries must have a name starting with a dot (\code{.}). Other entries must be scalar, and must be in the same order of all calls of \code{addOptPathEl}. Watch out: if \code{include.extra} was set to \code{TRUE} in (makeOptPathDF()) the list of extras is mandatory. Default is \code{NULL}.} \item{check.feasible}{(\code{logical(1)})\cr Should \code{x} be checked with (isFeasible())? Default is \code{TRUE}.} } \value{ Nothing. } \description{ Changes the argument in-place. Note that when adding parameters that have associated transformations, it is probably best to add the untransformed values to the path. Otherwise you have to switch off the feasibility check, as constraints might now not hold anymore. Dependent parameters whose requirements are not satisfied must be represented by a scalar NA in the input. } \examples{ ps = makeParamSet( makeNumericParam("p1"), makeDiscreteParam("p2", values = c("a", "b")) ) op = makeOptPathDF(par.set = ps, y.names = "y", minimize = TRUE) addOptPathEl(op, x = list(p1 = 7, p2 = "b"), y = 1) addOptPathEl(op, x = list(p1 = -1, p2 = "a"), y = 2) as.data.frame(op) } \seealso{ Other optpath: \code{\link{OptPath}}, \code{\link{getOptPathBestIndex}()}, \code{\link{getOptPathCols}()}, \code{\link{getOptPathCol}()}, \code{\link{getOptPathDOB}()}, \code{\link{getOptPathEOL}()}, \code{\link{getOptPathEl}()}, \code{\link{getOptPathErrorMessages}()}, \code{\link{getOptPathExecTimes}()}, \code{\link{getOptPathLength}()}, \code{\link{getOptPathParetoFront}()}, \code{\link{getOptPathX}()}, \code{\link{getOptPathY}()}, \code{\link{setOptPathElDOB}()}, \code{\link{setOptPathElEOL}()} } \concept{optpath} ParamHelpers/man/evaluateParamExpressions.Rd0000644000176000001440000000317313633666270021001 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/evaluateParamExpressions.R \name{evaluateParamExpressions} \alias{evaluateParamExpressions} \title{Evaluates all expressions within a parameter.} \usage{ evaluateParamExpressions(obj, dict = NULL) } \arguments{ \item{obj}{(\code{\link[=Param]{Param()}} | \code{\link[ParamHelpers:ParamSet]{ParamHelpers::ParamSet()}} | \code{list})\cr Parameter, parameter set or list of parameter values. Expressions within \code{len}, \code{lower} or \code{upper} boundaries, \code{default} or \code{values} will be evaluated using the provided dictionary (\code{dict}).} \item{dict}{(\code{environment} | \link{list} | \code{NULL})\cr Environment or list which will be used for evaluating the variables of expressions within a parameter, parameter set or list of parameters. The default is \code{NULL}.} } \value{ [\code{\link[=Param]{Param()}} | \code{\link[ParamHelpers:ParamSet]{ParamHelpers::ParamSet()}} | \code{list}]. } \description{ Evaluates the expressions of a parameter, parameter set or list of parameters for a given dictionary. } \examples{ ps = makeParamSet( makeNumericParam("x", lower = expression(p), upper = expression(ceiling(3 * p))), makeIntegerParam("y", lower = 1, upper = 2) ) evaluateParamExpressions(ps, dict = list(p = 3)) ps = makeParamSet( makeNumericParam("x", default = expression(sum(data$Species == "setosa"))), makeIntegerParam("y", lower = 1, upper = 2), keys = c("data", "Species") ) evaluateParamExpressions(ps, dict = list(data = iris)) par.vals = list( x = expression(k), y = 5 ) evaluateParamExpressions(par.vals, dict = list(k = 3)) } ParamHelpers/man/renderOptPathPlot.Rd0000644000176000001440000001733013636346430017361 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/renderOptPathPlot.R \name{renderOptPathPlot} \alias{renderOptPathPlot} \title{Function for plotting optimization paths.} \usage{ renderOptPathPlot( op, iter, x.over.time, y.over.time, contour.name = NULL, xlim = list(), ylim = list(), alpha = TRUE, log = NULL, colours = c("red", "blue", "green", "orange"), size.points = 3, size.lines = 1.5, impute.scale = 1, impute.value = "missing", scale = "std", ggplot.theme = ggplot2::theme(legend.position = "top"), marked = NULL, subset.obs, subset.vars, subset.targets, short.x.names, short.y.names, short.rest.names ) } \arguments{ \item{op}{\link{OptPath}\cr Optimization path.} \item{iter}{(\code{integer(1)})\cr Selected iteration of \code{x} to render plots for.} \item{x.over.time}{(\code{list} | NULL)\cr List of vectors of x-variables, either specified via name or id. If specified via names, also extra measurements from the opt.path can be selected. Maximum length for each vector is 5. For each list-element a line-plot iteration versus variable is generated. If the vector has length > 2 only mean values per iteration are plotted as lines, if vector has length 1 every point is plotted. Default is to plot all variables into as few plots as possible. Note that discrete variables are converted to numeric, if specified in the same vector with numerics. Moreover, if more than 1 point per iteration exists, mean values are calculated. This is also done for factor variables! We recommend you to specify this argument in a useful way.} \item{y.over.time}{(\code{list} | NULL)\cr List of vectors of y-variables, either specified via name or id. If specified via names, also extra measurements from the opt.path can be selected. Maximum length for each vector is 5. For each list-element a line-plot iteration versus variable is generated. If the vector has length > 2 only mean values per iteration are plotted as lines, if vector has length 1 every point is plotted. Default is to plot all variables into as few plots as possible. Note that discrete variables are converted to numeric, if specified in the same vector with numerics. Moreover, if more than 1 point per iteration exists, mean values are calculated. This is also done for factor variables! We recommend you to specify this argument in a useful way.} \item{contour.name}{(\code{character(1)} | NULL)\cr It is possible to overlay the XSpace plot with an contour plot. This is only possible, if the XSpace has exact 2 numeric and 0 discrete variable. Consider subsetting your variables to use this feature! contour.name is the name of the target variable that will be used for the contour lines. Default is to use the first target variable, if it is possible to add contour lines.} \item{xlim}{\link{list} \cr X axis limits for the plots. Must be a named list, so you can specify the axis limits for every plot. Every element of the list must be a numeric vector of length 2. Available names for elements are: XSpace - limits for the X-Space plot YSpace - limits for the Y-Space plot Default is an empty list - in this case limits are automatically set. Note: For some plots it is not meaningful to set limits, in this case the set limits are ignored. Note: We do not support setting lims for the over.time.plots. We think, in nearly every case the ggplot defaults are fine, and the very rare case you have to set them, you can you can extract the plots and add your own limits.} \item{ylim}{\link{list} \cr Y axis limits for the plots. Must be a named list, so you can specify the axis limits for every plot. Every element of the list must be a numeric vector of length 2. Available names for elements are: XSpace - limits for the X-Space plot YSpace - limits for the Y-Space plot Default is an empty list - in this case limits are automatically set. Note: For some plots it is not meaningful to set limits, in this case the set limits are ignored. Note: We do not support setting lims for the over.time.plots. We think, in nearly every case the ggplot defaults are fine, and the very rare case you have to set them, you can you can extract the plots and add your own limits.} \item{alpha}{(\code{logical(1)})\cr Activates or deactivates the alpha fading for the plots. Default is \code{TRUE}.} \item{log}{\link{character}\cr Vector of variable names. All of this variable logarithmized in every plot. Default is NULL - no logarithm is applied. Note that, if an variable has only negative value, it is multiplied with -1. For variables with both positive and negative values you have to do your own data preprocessing.} \item{colours}{(\code{character(4)})\cr Colours of the points/lines for the four point types init, seq, prob and marked. Default is red for init, blue for seq, green for prob and orange for marked.} \item{size.points}{(\code{numeric(4)} | NULL)\cr Size of points in the plot, default is 3.} \item{size.lines}{(\code{numeric(4)} | NULL)\cr Size of lines in the plots, default is 1.5.} \item{impute.scale}{(\code{numeric(1)})\cr Numeric missing values will be replaced by \code{max + impute.scale * (max - min)}. Default is \code{1}.} \item{impute.value}{(\code{character(1)})\cr Factor missing values will be replaced by \code{impute.value}. Default is \code{missing}.} \item{scale}{(\code{character(1)})\cr Parameter \code{scale} from the function \code{\link[GGally:ggparcoord]{GGally::ggparcoord()}} which is used for the multiD-case. Default is \code{std}.} \item{ggplot.theme}{Theme for the ggplots. Can be generated by \code{\link[ggplot2:theme]{ggplot2::theme()}}. Default is \code{ggplot2::theme(legend.position = "top")}.} \item{marked}{(\code{integer} | \code{character(1)} | NULL)\cr \dQuote{best} or indices of points that should be marked in the plots. If \code{marked = "best"} the best point for single crit optimization respectively the pareto front for multi crit optimization is marked. Default is \code{NULL} (no points are marked).} \item{subset.obs}{\link{integer}\cr Vector of indices to subset of observations to be plotted, default is all observations. All indices must be available in the opt.path. But, to enable subsetting over multiple iterations, not all indices must be available in the current iteration. Indices not available in the current iteration will be ignored. Default is all observations.} \item{subset.vars}{(\code{integer} | \code{character})\cr Subset of variables (x-variables) to be plotted. Either vector of indices or names. Default is all variables.} \item{subset.targets}{(\code{integer} | \code{character})\cr Subset of target variables (y-variables) to be plotted. Either vector of indices or names. Default is all variables} \item{short.x.names}{\link{character}\cr Short names for x variables that are used as axis labels. Note you can only give shortnames for variables you are using in \code{subset.vars}} \item{short.y.names}{\link{character}\cr Short names for y variables that are used as axis labels. Note you can only give shortnames for variables you are using in \code{subset.targets}} \item{short.rest.names}{\link{character}\cr Short names for rest variables that are used as axis labels. Note you can only give shortnames for variables you are used in \code{x.over.time} or \code{y.over.time}.} } \value{ List of plots. List has up to elements: plot.x: Plot for XSpace. If both X and Y are 1D, Plot for both plot.y: Plot for YSpace. If both X and Y are 1D, NULL. plot.x.over.time: List of plots for x over time. Can also be NULL. plot.y.over.time: List of plots for y over time. Can also be NULL. } \description{ Same as \code{\link[=plotOptPath]{plotOptPath()}}, but renders the plots for just 1 iteration and returns a list of plots instead of printing the plot. Useful, if you want to extract single plots or to edit the ggplots by yourself. } ParamHelpers/man/getOptPathDOB.Rd0000644000176000001440000000240513633666270016350 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/OptPath_getter.R \name{getOptPathDOB} \alias{getOptPathDOB} \title{Get date-of-birth vector from the optimization path.} \usage{ getOptPathDOB(op, dob, eol) } \arguments{ \item{op}{\link{OptPath}\cr Optimization path.} \item{dob}{\link{integer}\cr Vector of date-of-birth values to further subset the result. Only elements with a date-of-birth included in \code{dob} are selected. Default is all.} \item{eol}{\link{integer}\cr Vector of end-of-life values to further subset the result. Only elements with an end-of-life included in \code{eol} are selected. Default is all.} } \value{ \link{integer}. } \description{ Get date-of-birth vector from the optimization path. } \seealso{ Other optpath: \code{\link{OptPath}}, \code{\link{addOptPathEl}()}, \code{\link{getOptPathBestIndex}()}, \code{\link{getOptPathCols}()}, \code{\link{getOptPathCol}()}, \code{\link{getOptPathEOL}()}, \code{\link{getOptPathEl}()}, \code{\link{getOptPathErrorMessages}()}, \code{\link{getOptPathExecTimes}()}, \code{\link{getOptPathLength}()}, \code{\link{getOptPathParetoFront}()}, \code{\link{getOptPathX}()}, \code{\link{getOptPathY}()}, \code{\link{setOptPathElDOB}()}, \code{\link{setOptPathElEOL}()} } \concept{optpath} ParamHelpers/man/isTypeString.Rd0000644000176000001440000000214013633666270016404 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/isTypeString.R \name{isTypeString} \alias{isTypeString} \alias{isNumericTypeString} \alias{isIntegerTypeString} \alias{isCharacterTypeString} \alias{isDiscreteTypeString} \alias{isLogicalTypeString} \alias{isVectorTypeString} \title{Check if type string is of certain type.} \usage{ isNumericTypeString(type, include.int = TRUE) isIntegerTypeString(type) isCharacterTypeString(type) isDiscreteTypeString(type, include.logical = TRUE) isLogicalTypeString(type) isVectorTypeString(type) } \arguments{ \item{type}{(\code{character(1)})\cr Type string.} \item{include.int}{(\code{logical(1)})\cr Are integers also considered to be numeric? Default is \code{TRUE}.} \item{include.logical}{(\code{logical(1)})\cr Are logicals also considered to be discrete? Default is \code{TRUE}.} } \value{ (\code{logical(1)}) } \description{ \code{TRUE} iff the type string is a certain type, e.g. \code{isIntegerTypeString} checks if we have \dQuote{integer} or \dQuote{integervector}, and \code{isVectorTypeString} check if we have \dQuote{*vector}. } ParamHelpers/man/makeParamSet.Rd0000644000176000001440000000551713633666270016325 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ParamSet.R \name{makeParamSet} \alias{makeParamSet} \alias{ParamSet} \alias{makeNumericParamSet} \title{Construct a parameter set.} \usage{ makeParamSet(..., params = NULL, forbidden = NULL, keys = NULL) makeNumericParamSet(id = "x", len, lower = -Inf, upper = Inf, vector = TRUE) } \arguments{ \item{...}{(\code{\link[=Param]{Param()}})\cr Parameters.} \item{params}{(list of \code{\link[=Param]{Param()}})\cr List of parameters, alternative way instead of using \code{...}.} \item{forbidden}{(\code{NULL} | R expression)\cr States forbidden region of parameter set via an expression. Every setting which satisfies this expression is considered to be infeasible. This makes it possible to exclude more complex region of the parameter space than through simple constraints or \code{requires}-conditions (although these should be always used when possible). If parameters have associated trafos, the forbidden region must always be specified on the original scale and not the transformed one. Default is \code{NULL} which means no forbidden region.} \item{keys}{\link{character}\cr Character vector with keys (names) of feasible variable names which will be provided via a dictionary/hash later. Default is \code{NULL}.} \item{id}{(\code{character(1)})\cr Name of parameter.} \item{len}{(\code{integer(1)})\cr Length of vector.} \item{lower}{(\code{numeric})\cr Lower bound. Default is \code{-Inf}.} \item{upper}{\link{numeric} \cr Upper bound. Default is \code{Inf}.} \item{vector}{(\code{logical(1)}) \cr Should a \code{NumericVectorParam} be used instead of n \code{NumericParam} objects? Default is \code{TRUE}.} } \value{ \code{\link[=ParamSet]{ParamSet()}} | \code{LearnerParamSet}. If all parameters of the \code{ParamSet} are learner parameters, the output will inherit the class \code{LearnerParamSet}. } \description{ \code{makeParamSet}: Construct from a bunch of parameters. Multiple sets can be concatenated with \code{c}. The constructed S3 class is simply a list that contains the element \code{pars}. \code{pars} is a list of the passed parameters, named by their ids. If \code{keys} are provided it will automatically be checked whether all expressions within the provided parameters only contain arguments that are a subset of keys. } \examples{ makeParamSet( makeNumericParam("u", lower = 1), makeIntegerParam("v", lower = 1, upper = 2), makeDiscreteParam("w", values = 1:2), makeLogicalParam("x"), makeDiscreteVectorParam("y", len = 2, values = c("a", "b")) ) makeParamSet( makeNumericParam("u", lower = expression(ceiling(n))), makeIntegerParam("v", lower = expression(floor(n)), upper = 2), keys = c("p", "n") ) makeParamSet( makeNumericParam("min", lower = 0, upper = 0.8), makeNumericParam("max", lower = 0.2, upper = 1), forbidden = expression(min > max) ) } ParamHelpers/man/filterParams.Rd0000644000176000001440000000563013633666270016400 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/filterParams.R \name{filterParams} \alias{filterParams} \alias{filterParamsNumeric} \alias{filterParamsDiscrete} \title{Get parameter subset of only certain parameters.} \usage{ filterParams( par.set, ids = NULL, type = NULL, tunable = c(TRUE, FALSE), check.requires = FALSE ) filterParamsNumeric( par.set, ids = NULL, tunable = c(TRUE, FALSE), include.int = TRUE ) filterParamsDiscrete( par.set, ids = NULL, tunable = c(TRUE, FALSE), include.logical = TRUE ) } \arguments{ \item{par.set}{\link{ParamSet}\cr Parameter set.} \item{ids}{(\code{NULL} | \code{character})\cr Vector with id strings containing the parameters to select. Has to be a subset of the parameter names within the parameter set. Per default (\code{ids = NULL}) no filtering based on names is done.} \item{type}{(\code{NULL} | \code{character})\cr Vector of allowed types, subset of: \dQuote{numeric}, \dQuote{integer}, \dQuote{numericvector}, \dQuote{integervector}, \dQuote{discrete}, \dQuote{discretevector}, \dQuote{logical}, \dQuote{logicalvector}, \dQuote{character}, \dQuote{charactervector}, \dQuote{function}, \dQuote{untyped}. Setting \code{type = NULL}, which is the default, allows the consideration of all types.} \item{tunable}{(\code{logical})\cr Vector of allowed values for the property \code{tunable}. Accepted arguments are \code{TRUE}, \code{FALSE} or \code{c(TRUE, FALSE)}. The default is \code{c(TRUE, FALSE)}, i.e. none of the parameters will be filtered out.} \item{check.requires}{(\code{logical(1)})\cr Toggle whether it should be checked that all requirements in the (ParamSet()) are still valid after filtering or not. This check is done after filtering and will throw an error if those Params are filtered which other Params need for their requirements. Default is \code{FALSE}.} \item{include.int}{(\code{logical(1)})\cr Are integers also considered to be numeric? Default is \code{TRUE}.} \item{include.logical}{(\code{logical(1)})\cr Are logicals also considered to be discrete? Default is \code{TRUE}.} } \value{ \code{\link[=ParamSet]{ParamSet()}}. } \description{ Parameter order is not changed. It is possible to filter via multiple arguments, e.g., first filter based on id, then the type and lastly tunable. The order in which the filters are executed is always fixed (id > type > tunable). } \examples{ ps = makeParamSet( makeNumericParam("u", lower = 1), makeIntegerParam("v", lower = 1, upper = 2), makeDiscreteParam("w", values = 1:2), makeLogicalParam("x"), makeCharacterParam("s"), makeNumericParam("y", tunable = FALSE) ) # filter for numeric and integer parameters filterParams(ps, type = c("integer", "numeric")) # filter for tunable, numeric parameters filterParams(ps, type = "numeric", tunable = TRUE) # filter for all numeric parameters among "u", "v" and "x" filterParams(ps, type = "numeric", ids = c("u", "v", "x")) } ParamHelpers/man/plotEAF.Rd0000644000176000001440000000252513633666270015241 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/OptPath_plotEAF.R \name{plotEAF} \alias{plotEAF} \title{Plots attainment functions for data stored in multiple OptPaths.} \usage{ plotEAF(opt.paths, xlim = NULL, ylim = NULL, ...) } \arguments{ \item{opt.paths}{(\code{list})\cr List of list of \code{OptPath} objects. First index is the algorithm / major variation in the experiment, second index is the index of the replicated run.} \item{xlim}{(\code{numeric(2)})\cr The x limits (x1, x2) of the plot.} \item{ylim}{(\code{numeric(2)})\cr The y limits (y1, y2) of the plot.} \item{...}{(any)\cr Passed on to \code{\link[eaf:eafplot]{eaf::eafplot()}}.} } \value{ \code{\link{data.frame}} Invisibly returns the data passed to \code{\link[eaf:eafplot]{eaf::eafplot()}}. } \description{ Can be used to plot OptPaths where information for bi-objective evaluation was logged for repeated runs of different algorithmic runs. Pretty directly calls \code{\link[eaf:eafplot]{eaf::eafplot()}}. } \note{ We changed the defaults of \code{\link[eaf:eafplot]{eaf::eafplot()}} in the following way: The axis are labeled by \code{y.names}, colors are set to our favorite grey values and linetypes changed, too. With our colors / linetypes default it is possible to distinguish 6 different algorithms. But this can again be overwritten by the user. } ParamHelpers/man/getOptPathParetoFront.Rd0000644000176000001440000000417113633666270020211 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/OptPath_getter.R \name{getOptPathParetoFront} \alias{getOptPathParetoFront} \title{Get indices of pareto front of optimization path.} \usage{ getOptPathParetoFront( op, y.names = op$y.names, dob = op$env$dob, eol = op$env$eol, index = FALSE ) } \arguments{ \item{op}{\link{OptPath}\cr Optimization path.} \item{y.names}{\link{character}\cr Names of performance measures to construct pareto front for. Default is all performance measures.} \item{dob}{\link{integer}\cr Vector of date-of-birth values to further subset the result. Only elements with a date-of-birth included in \code{dob} are selected. Default is all.} \item{eol}{\link{integer}\cr Vector of end-of-life values to further subset the result. Only elements with an end-of-life included in \code{eol} are selected. Default is all.} \item{index}{(\code{logical(1)})\cr Return indices into path of front or y-matrix of nondominated points? Default is \code{FALSE}.} } \value{ \code{matrix} | \code{integer}. Either matrix (with named columns) of points of front in objective space or indices into path for front. } \description{ Get indices of pareto front of optimization path. } \examples{ ps = makeParamSet(makeNumericParam("x")) op = makeOptPathDF(par.set = ps, y.names = c("y1", "y2"), minimize = c(TRUE, TRUE)) addOptPathEl(op, x = list(x = 1), y = c(5, 3)) addOptPathEl(op, x = list(x = 2), y = c(2, 4)) addOptPathEl(op, x = list(x = 3), y = c(9, 4)) addOptPathEl(op, x = list(x = 4), y = c(4, 9)) as.data.frame(op) getOptPathParetoFront(op) getOptPathParetoFront(op, index = TRUE) } \seealso{ Other optpath: \code{\link{OptPath}}, \code{\link{addOptPathEl}()}, \code{\link{getOptPathBestIndex}()}, \code{\link{getOptPathCols}()}, \code{\link{getOptPathCol}()}, \code{\link{getOptPathDOB}()}, \code{\link{getOptPathEOL}()}, \code{\link{getOptPathEl}()}, \code{\link{getOptPathErrorMessages}()}, \code{\link{getOptPathExecTimes}()}, \code{\link{getOptPathLength}()}, \code{\link{getOptPathX}()}, \code{\link{getOptPathY}()}, \code{\link{setOptPathElDOB}()}, \code{\link{setOptPathElEOL}()} } \concept{optpath} ParamHelpers/man/getParamNr.Rd0000644000176000001440000000124013633666270016000 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/getParamNr.R \name{getParamNr} \alias{getParamNr} \title{Return number of parameters in set.} \usage{ getParamNr(par.set, devectorize = FALSE) } \arguments{ \item{par.set}{\link{ParamSet}\cr Parameter set.} \item{devectorize}{(\code{logical(1)})\cr Sum over length of vector parameters? Default is code{FALSE}.} } \value{ \code{\link{integer}}. } \description{ Either number of parameters or sum over parameter lengths. } \examples{ ps = makeParamSet( makeNumericParam("u"), makeDiscreteVectorParam("x", len = 2, values = c("a", "b")) ) getParamNr(ps) getParamNr(ps, devectorize = TRUE) } ParamHelpers/man/generateRandomDesign.Rd0000644000176000001440000000446213633666270020036 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/generateRandomDesign.R \name{generateRandomDesign} \alias{generateRandomDesign} \title{Generates a random design for a parameter set.} \usage{ generateRandomDesign(n = 10L, par.set, trafo = FALSE) } \arguments{ \item{n}{(\code{integer(1)})\cr Number of samples in design. Default is 10.} \item{par.set}{\link{ParamSet}\cr Parameter set.} \item{trafo}{(\code{logical(1)})\cr Transform all parameters by using theirs respective transformation functions. Default is \code{FALSE}.} } \value{ \link{data.frame}. Columns are named by the ids of the parameters. If the \code{par.set} argument contains a vector parameter, its corresponding column names in the design are the parameter id concatenated with 1 to dimension of the vector. The result will have an \code{logical(1)} attribute \dQuote{trafo}, which is set to the value of argument \code{trafo}. } \description{ The following types of columns are created: \tabular{ll}{ numeric(vector) \tab \code{numeric} \cr integer(vector) \tab \code{integer} \cr discrete(vector) \tab \code{factor} (names of values = levels) \cr logical(vector) \tab \code{logical} } If you want to convert these, look at \code{\link[BBmisc:convertDataFrameCols]{BBmisc::convertDataFrameCols()}}. For discrete vectors the levels and their order will be preserved, even if not all levels are present. The algorithm simply calls \code{\link[=sampleValues]{sampleValues()}} and arranges the result in a data.frame. Parameters are trafoed (potentially, depending on the setting of argument \code{trafo}); dependent parameters whose constraints are unsatisfied are set to \code{NA} entries. \code{generateRandomDesign} will NOT work if there are dependencies over multiple levels of parameters and the dependency is only given with respect to the \dQuote{previous} parameter. A current workaround is to state all dependencies on all parameters involved. (We are working on it.) Note that if you have trafos attached to your params, the complete creation of the design (except for the detection of invalid parameters w.r.t to their \code{requires} setting) takes place on the UNTRANSFORMED scale. So this function samples from a uniform density over the param space on the UNTRANSFORMED scale, but not necessarily the transformed scale. } ParamHelpers/man/hasForbidden.Rd0000644000176000001440000000055713633666270016342 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/hasForbidden.R \name{hasForbidden} \alias{hasForbidden} \title{Check parameter set for forbidden region.} \usage{ hasForbidden(par.set) } \arguments{ \item{par.set}{\link{ParamSet}\cr Parameter set.} } \value{ \code{logical(1)}. } \description{ Check parameter set for forbidden region. } ParamHelpers/man/getOptPathBestIndex.Rd0000644000176000001440000000431113633666270017627 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/OptPath_getter.R \name{getOptPathBestIndex} \alias{getOptPathBestIndex} \title{Get index of the best element from optimization path.} \usage{ getOptPathBestIndex( op, y.name = op$y.names[1], dob = op$env$dob, eol = op$env$eol, ties = "last" ) } \arguments{ \item{op}{\link{OptPath}\cr Optimization path.} \item{y.name}{(\code{character(1)})\cr Name of target value to decide which element is best. Default is \code{y.names[1]}.} \item{dob}{\link{integer}\cr Vector of date-of-birth values to further subset the result. Only elements with a date-of-birth included in \code{dob} are selected. Default is all.} \item{eol}{\link{integer}\cr Vector of end-of-life values to further subset the result. Only elements with an end-of-life included in \code{eol} are selected. Default is all.} \item{ties}{(\code{character(1)})\cr How should ties be broken when more than one optimal element is found? \dQuote{all}: return all indices, \dQuote{first}: return first optimal element in path, \dQuote{last}: return last optimal element in path, \dQuote{random}: return random optimal element in path. Default is \dQuote{last}.} } \value{ \code{\link{integer}} Index or indices into path. See \code{ties}. } \description{ Get index of the best element from optimization path. } \examples{ ps = makeParamSet(makeNumericParam("x")) op = makeOptPathDF(par.set = ps, y.names = "y", minimize = TRUE) addOptPathEl(op, x = list(x = 1), y = 5) addOptPathEl(op, x = list(x = 2), y = 3) addOptPathEl(op, x = list(x = 3), y = 9) addOptPathEl(op, x = list(x = 4), y = 3) as.data.frame(op) getOptPathBestIndex(op) getOptPathBestIndex(op, ties = "first") } \seealso{ Other optpath: \code{\link{OptPath}}, \code{\link{addOptPathEl}()}, \code{\link{getOptPathCols}()}, \code{\link{getOptPathCol}()}, \code{\link{getOptPathDOB}()}, \code{\link{getOptPathEOL}()}, \code{\link{getOptPathEl}()}, \code{\link{getOptPathErrorMessages}()}, \code{\link{getOptPathExecTimes}()}, \code{\link{getOptPathLength}()}, \code{\link{getOptPathParetoFront}()}, \code{\link{getOptPathX}()}, \code{\link{getOptPathY}()}, \code{\link{setOptPathElDOB}()}, \code{\link{setOptPathElEOL}()} } \concept{optpath} ParamHelpers/man/listToDfOneRow.Rd0000644000176000001440000000126313633666270016627 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/listToDfOneRow.R \name{listToDfOneRow} \alias{listToDfOneRow} \title{Convert a list to a data.frame with one row} \usage{ listToDfOneRow(l) } \arguments{ \item{l}{(\code{list})\cr of atomic values of vectors.} } \value{ (\code{data.frame}) with only one row, containing the list elements. } \description{ Convert a list of vectors or scalars to a \code{data.frame} with only one row. Names of the columns correspond to the names of elements in the list. If a vector is one list element it is spread over multiple columns and named sequentially, e.g. \code{a = c(5,7)} becomes \code{data.frame(a1 = 5, a2 = 7)}. } ParamHelpers/man/sampleValue.Rd0000644000176000001440000000302013636350110016176 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/sample.R \name{sampleValue} \alias{sampleValue} \title{Sample a random value from a parameter or a parameter set uniformly.} \usage{ sampleValue(par, discrete.names = FALSE, trafo = FALSE) } \arguments{ \item{par}{(\link{Param} | \link{ParamSet})\cr Parameter or parameter set.} \item{discrete.names}{(\code{logical(1)})\cr Should names be sampled for discrete parameters or values instead? Default is code {FALSE}.} \item{trafo}{(\code{logical(1)})\cr Transform all parameters by using theirs respective transformation functions. Default is \code{FALSE}.} } \value{ The return type is determined by the type of the parameter. For a set a named list of such values in the correct order is returned. } \description{ Sample a random value from a parameter or a parameter set uniformly. Dependent parameters whose requirements are not satisfied are represented by a scalar NA in the output. } \examples{ # bounds are necessary here, can't sample with Inf bounds: u = makeNumericParam("x", lower = 0, upper = 1) # returns a random number between 0 and 1: sampleValue(u) p = makeDiscreteParam("x", values = c("a", "b", "c")) # can be either "a", "b" or "c" sampleValue(p) p = makeIntegerVectorParam("x", len = 2, lower = 1, upper = 5) # vector of two random integers between 1 and 5: sampleValue(p) ps = makeParamSet( makeNumericParam("x", lower = 1, upper = 10), makeIntegerParam("y", lower = 1, upper = 10), makeDiscreteParam("z", values = 1:2) ) sampleValue(ps) } ParamHelpers/man/generateDesignOfDefaults.Rd0000644000176000001440000000332613633666270020650 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/generateDesignOfDefaults.R \name{generateDesignOfDefaults} \alias{generateDesignOfDefaults} \title{Generates a design with the defaults of a parameter set.} \usage{ generateDesignOfDefaults(par.set, trafo = FALSE) } \arguments{ \item{par.set}{\link{ParamSet}\cr Parameter set.} \item{trafo}{(\code{logical(1)})\cr Transform all parameters by using theirs respective transformation functions. Default is \code{FALSE}.} } \value{ \link{data.frame}. Columns are named by the ids of the parameters. If the \code{par.set} argument contains a vector parameter, its corresponding column names in the design are the parameter id concatenated with 1 to dimension of the vector. The result will have an \code{logical(1)} attribute \dQuote{trafo}, which is set to the value of argument \code{trafo}. } \description{ The following types of columns are created: \tabular{ll}{ numeric(vector) \tab \code{numeric} \cr integer(vector) \tab \code{integer} \cr discrete(vector) \tab \code{factor} (names of values = levels) \cr logical(vector) \tab \code{logical} } This will create a design containing only one point at the default values of the supplied param set. In most cases you will combine the resulting \code{data.frame} with a different generation function e.g. \code{\link[=generateDesign]{generateDesign()}}, \code{\link[=generateRandomDesign]{generateRandomDesign()}} or \code{\link[=generateGridDesign]{generateGridDesign()}}. This is useful to force an evaluation at the default location of the parameters while still generating a design. Parameters default values, whose conditions (\code{requires}) are not fulfilled will be set to \code{NA} in the result. } ParamHelpers/man/getParamLengths.Rd0000644000176000001440000000222713633666270017033 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/getParamLengths.R \name{getParamLengths} \alias{getParamLengths} \title{Return lengths of single parameters or parameters in parameter set.} \usage{ getParamLengths(par, dict = NULL) } \arguments{ \item{par}{(\link{Param} | \link{ParamSet})\cr Parameter or parameter set.} \item{dict}{(\code{environment} | \link{list} | \code{NULL})\cr Environment or list which will be used for evaluating the variables of expressions within a parameter, parameter set or list of parameters. The default is \code{NULL}.} } \value{ (\code{integer}). Named and in the same order as the input for \code{\link[=ParamSet]{ParamSet()}} input. } \description{ Useful for vector parameters. } \examples{ ps = makeParamSet( makeNumericParam("u"), makeIntegerParam("v", lower = 1, upper = 2), makeDiscreteParam("w", values = 1:2), makeDiscreteVectorParam("x", len = 2, values = c("a", "b")) ) getParamLengths(ps) # the length of the vector x is 2, for all other single value parameters the length is 1. par = makeNumericVectorParam("x", len = expression(k), lower = 0) getParamLengths(par, dict = list(k = 4)) } ParamHelpers/man/getOptPathX.Rd0000644000176000001440000000253213633666270016154 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/OptPath_getter.R \name{getOptPathX} \alias{getOptPathX} \title{Get data.frame of input points (X-space) referring to the param set from the optimization path.} \usage{ getOptPathX(op, dob, eol) } \arguments{ \item{op}{\link{OptPath}\cr Optimization path.} \item{dob}{\link{integer}\cr Vector of date-of-birth values to further subset the result. Only elements with a date-of-birth included in \code{dob} are selected. Default is all.} \item{eol}{\link{integer}\cr Vector of end-of-life values to further subset the result. Only elements with an end-of-life included in \code{eol} are selected. Default is all.} } \value{ \link{data.frame}. } \description{ Get data.frame of input points (X-space) referring to the param set from the optimization path. } \seealso{ Other optpath: \code{\link{OptPath}}, \code{\link{addOptPathEl}()}, \code{\link{getOptPathBestIndex}()}, \code{\link{getOptPathCols}()}, \code{\link{getOptPathCol}()}, \code{\link{getOptPathDOB}()}, \code{\link{getOptPathEOL}()}, \code{\link{getOptPathEl}()}, \code{\link{getOptPathErrorMessages}()}, \code{\link{getOptPathExecTimes}()}, \code{\link{getOptPathLength}()}, \code{\link{getOptPathParetoFront}()}, \code{\link{getOptPathY}()}, \code{\link{setOptPathElDOB}()}, \code{\link{setOptPathElEOL}()} } \concept{optpath} ParamHelpers/man/paramValueToString.Rd0000644000176000001440000000323513633666270017535 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/paramValueToString.R \name{paramValueToString} \alias{paramValueToString} \title{Convert a value to a string.} \usage{ paramValueToString(par, x, show.missing.values = FALSE, num.format = "\%.3g") } \arguments{ \item{par}{(\link{Param} | \link{ParamSet})\cr Parameter or parameter set.} \item{x}{(any)\cr Value for parameter or value for parameter set. In the latter case it must be named list. For discrete parameters their values must be used, not their names.} \item{show.missing.values}{(\code{logical(1)})\cr Display \dQuote{NA} for parameters, which have no setting, because their requirements are not satisfied (dependent parameters), instead of displaying nothing? Default is \code{FALSE}.} \item{num.format}{(\code{character(1)})\cr Number format for output of numeric parameters. See the details section of the manual for \code{\link[base:sprintf]{base::sprintf()}} for details.} } \value{ \code{character(1)}. } \description{ Useful helper for logging. For discrete parameter values always the name of the discrete value is used. } \examples{ p = makeNumericParam("x") paramValueToString(p, 1) paramValueToString(p, 1.2345) paramValueToString(p, 0.000039) paramValueToString(p, 8.13402, num.format = "\%.2f") p = makeIntegerVectorParam("x", len = 2) paramValueToString(p, c(1L, 2L)) p = makeLogicalParam("x") paramValueToString(p, TRUE) p = makeDiscreteParam("x", values = list(a = NULL, b = 2)) paramValueToString(p, NULL) ps = makeParamSet( makeNumericVectorParam("x", len = 2L), makeDiscreteParam("y", values = list(a = NULL, b = 2)) ) paramValueToString(ps, list(x = c(1, 2), y = NULL)) } ParamHelpers/man/trafoOptPath.Rd0000644000176000001440000000167513633666270016367 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/trafo.R \name{trafoOptPath} \alias{trafoOptPath} \title{Transform optimization path.} \usage{ trafoOptPath(opt.path) } \arguments{ \item{opt.path}{[\code{\link[=OptPath]{OptPath()}}]\cr Optimization path.} } \value{ [\code{\link[=OptPath]{OptPath()}}]. } \description{ Transform optimization path with associated transformation functions of parameters. Can only be done when x values where added \dQuote{untransformed}. } \examples{ ps = makeParamSet( makeIntegerParam("u", trafo = function(x) 2 * x), makeNumericVectorParam("v", len = 2, trafo = function(x) x / sum(x)), makeDiscreteParam("w", values = c("a", "b")) ) op = makeOptPathDF(ps, y.names = "y", minimize = TRUE) addOptPathEl(op, x = list(3, c(2, 4), "a"), y = 0, dob = 1, eol = 1) addOptPathEl(op, x = list(4, c(5, 3), "b"), y = 2, dob = 5, eol = 7) as.data.frame(op) op = trafoOptPath(op) as.data.frame(op) } ParamHelpers/man/generateGridDesign.Rd0000644000176000001440000000577713636350110017477 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/generateGridDesign.R \name{generateGridDesign} \alias{generateGridDesign} \title{Generates a grid design for a parameter set.} \usage{ generateGridDesign(par.set, resolution, trafo = FALSE) } \arguments{ \item{par.set}{\link{ParamSet}\cr Parameter set.} \item{resolution}{(\code{integer})\cr Resolution of the grid for each numeric/integer parameter in \code{par.set}. For vector parameters, it is the resolution per dimension. Either pass one resolution for all parameters, or a named vector.} \item{trafo}{(\code{logical(1)})\cr Transform all parameters by using theirs respective transformation functions. Default is \code{FALSE}.} } \value{ \link{data.frame}. Columns are named by the ids of the parameters. If the \code{par.set} argument contains a vector parameter, its corresponding column names in the design are the parameter id concatenated with 1 to dimension of the vector. The result will have an \code{logical(1)} attribute \dQuote{trafo}, which is set to the value of argument \code{trafo}. } \description{ The following types of columns are created: \tabular{ll}{ numeric(vector) \tab \code{numeric} \cr integer(vector) \tab \code{integer} \cr discrete(vector) \tab \code{factor} (names of values = levels) \cr logical(vector) \tab \code{logical} } If you want to convert these, look at \code{\link[BBmisc:convertDataFrameCols]{BBmisc::convertDataFrameCols()}}. Dependent parameters whose constraints are unsatisfied generate \code{NA} entries in their respective columns. For discrete vectors the levels and their order will be preserved. The algorithm currently performs these steps: \enumerate{ \item{We create a grid. For numerics and integers we use the specified resolution. For discretes all values will be taken.} \item{Forbidden points are removed.} \item{Parameters are trafoed (potentially, depending on the setting of argument \code{trafo}); dependent parameters whose constraints are unsatisfied are set to \code{NA} entries.} \item{Duplicated points are removed. Duplicated points are not generated in a grid design, but the way parameter dependencies are handled make this possible.} } Note that if you have trafos attached to your params, the complete creation of the design (except for the detection of invalid parameters w.r.t to their \code{requires} setting) takes place on the UNTRANSFORMED scale. So this function creates a regular grid over the param space on the UNTRANSFORMED scale, but not necessarily the transformed scale. \code{generateDesign} will NOT work if there are dependencies over multiple levels of parameters and the dependency is only given with respect to the \dQuote{previous} parameter. A current workaround is to state all dependencies on all parameters involved. (We are working on it.) } \examples{ ps = makeParamSet( makeNumericParam("x1", lower = -2, upper = 1), makeNumericParam("x2", lower = -2, upper = 2, trafo = function(x) x^2) ) generateGridDesign(ps, resolution = c(x1 = 4, x2 = 5), trafo = TRUE) } ParamHelpers/man/trafoValue.Rd0000644000176000001440000000210213633666270016046 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/trafo.R \name{trafoValue} \alias{trafoValue} \title{Transform a value.} \usage{ trafoValue(par, x) } \arguments{ \item{par}{(\link{Param} | \link{ParamSet})\cr Parameter or parameter set.} \item{x}{(any) \cr Single value to check. For a parameter set this must be a list. If the list is unnamed (not recommended) it must be in the same order as the param set. If it is named, its names must match the parameter names in the param set.} } \value{ Transformed value. } \description{ Transform a value with associated transformation function(s). } \examples{ # transform simple parameter: p = makeNumericParam(id = "x", trafo = function(x) x^2) trafoValue(p, 2) # for a parameter set different transformation functions are possible: ps = makeParamSet( makeIntegerParam("u", trafo = function(x) 2 * x), makeNumericVectorParam("v", len = 2, trafo = function(x) x / sum(x)), makeDiscreteParam("w", values = c("a", "b")) ) # now the values of "u" and "v" are transformed: trafoValue(ps, list(3, c(2, 4), "a")) } ParamHelpers/man/getOptPathErrorMessages.Rd0000644000176000001440000000243313633666270020526 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/OptPath_getter.R \name{getOptPathErrorMessages} \alias{getOptPathErrorMessages} \title{Get error-message vector from the optimization path.} \usage{ getOptPathErrorMessages(op, dob, eol) } \arguments{ \item{op}{\link{OptPath}\cr Optimization path.} \item{dob}{\link{integer}\cr Vector of date-of-birth values to further subset the result. Only elements with a date-of-birth included in \code{dob} are selected. Default is all.} \item{eol}{\link{integer}\cr Vector of end-of-life values to further subset the result. Only elements with an end-of-life included in \code{eol} are selected. Default is all.} } \value{ \link{character}. } \description{ Get error-message vector from the optimization path. } \seealso{ Other optpath: \code{\link{OptPath}}, \code{\link{addOptPathEl}()}, \code{\link{getOptPathBestIndex}()}, \code{\link{getOptPathCols}()}, \code{\link{getOptPathCol}()}, \code{\link{getOptPathDOB}()}, \code{\link{getOptPathEOL}()}, \code{\link{getOptPathEl}()}, \code{\link{getOptPathExecTimes}()}, \code{\link{getOptPathLength}()}, \code{\link{getOptPathParetoFront}()}, \code{\link{getOptPathX}()}, \code{\link{getOptPathY}()}, \code{\link{setOptPathElDOB}()}, \code{\link{setOptPathElEOL}()} } \concept{optpath} ParamHelpers/man/getOptPathLength.Rd0000644000176000001440000000170513633666270017167 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/OptPath_getter.R \name{getOptPathLength} \alias{getOptPathLength} \title{Get the length of the optimization path.} \usage{ getOptPathLength(op) } \arguments{ \item{op}{\link{OptPath}\cr Optimization path.} } \value{ \code{integer(1)} } \description{ Dependent parameters whose requirements are not satisfied are represented by a scalar NA in the output. } \seealso{ Other optpath: \code{\link{OptPath}}, \code{\link{addOptPathEl}()}, \code{\link{getOptPathBestIndex}()}, \code{\link{getOptPathCols}()}, \code{\link{getOptPathCol}()}, \code{\link{getOptPathDOB}()}, \code{\link{getOptPathEOL}()}, \code{\link{getOptPathEl}()}, \code{\link{getOptPathErrorMessages}()}, \code{\link{getOptPathExecTimes}()}, \code{\link{getOptPathParetoFront}()}, \code{\link{getOptPathX}()}, \code{\link{getOptPathY}()}, \code{\link{setOptPathElDOB}()}, \code{\link{setOptPathElEOL}()} } \concept{optpath} ParamHelpers/man/repairPoint.Rd0000644000176000001440000000134013633666270016235 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/repairPoint.R \name{repairPoint} \alias{repairPoint} \title{Repairs values of numeric and integer parameters out side of constraints.} \usage{ repairPoint(par.set, x, warn = FALSE) } \arguments{ \item{par.set}{\link{ParamSet}\cr Parameter set.} \item{x}{\link{list}\cr List of parameter values. Must be in correct order. Values corresponding to non-numeric/integer types are left unchanged.} \item{warn}{(\code{logical(1)})\cr Boolean indicating whether a warning should be printed each time a value is repaired. Default is \code{FALSE}.} } \value{ \link{list}: List of repaired points. } \description{ Clips values outside of box constraints to bounds. } ParamHelpers/man/discreteNameToValue.Rd0000644000176000001440000000152513633666270017651 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/convertDiscrete.R \name{discreteNameToValue} \alias{discreteNameToValue} \title{Convert encoding name(s) to discrete value(s).} \usage{ discreteNameToValue(par, name) } \arguments{ \item{par}{\link{Param}\cr Parameter.} \item{name}{(\code{character})\cr Name (string) encoding the value for a discrete parameter, or a character vector of names for a discrete vector.} } \value{ \link{any}. Parameter value for a discrete parameter or a list of values for a discrete vector. } \description{ For a discrete parameter or discrete vector. If the \code{name} is \code{NA}, indicating a missing parameter value due to unsatisfied requirements, \code{NA} is returned. } \examples{ p = makeDiscreteParam("u", values = c(x1 = "a", x2 = "b", x3 = "b")) discreteNameToValue(p, "x3") } ParamHelpers/man/removeMissingValues.Rd0000644000176000001440000000063013633666270017751 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/removeMissingValues.R \name{removeMissingValues} \alias{removeMissingValues} \title{Removes all scalar NAs from a parameter setting list.} \usage{ removeMissingValues(x) } \arguments{ \item{x}{\link{list}\cr List of parameter values.} } \value{ \link{list}. } \description{ Removes all scalar NAs from a parameter setting list. } ParamHelpers/man/isFeasible.Rd0000644000176000001440000000461613633666270016020 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/isFeasible.R \name{isFeasible} \alias{isFeasible} \title{Check if parameter value is valid.} \usage{ isFeasible(par, x, use.defaults = FALSE, filter = FALSE) } \arguments{ \item{par}{(\link{Param} | \link{ParamSet})\cr Parameter or parameter set.} \item{x}{(any) \cr Single value to check against the \code{Param} or \code{ParamSet}. For a \code{ParamSet} \code{x} must be a list. \code{x} has to contain the untransformed values. If the list is named, it is possible to only pass a subset of parameters defined in the \code{\link[=ParamSet]{ParamSet()}} \code{par}. In that case, only conditions regarding the passed parameters are checked. (Note that this might not work if one of the passed params has a \code{requires} setting which refers to an unpassed param.)} \item{use.defaults}{(\code{logical(1)})\cr Whether defaults of the \code{\link[=Param]{Param()}}/\code{\link[=ParamSet]{ParamSet()}} should be used if no values are supplied. If the defaults have requirements that are not met by \code{x} it will be feasible nonetheless. Default is \code{FALSE}.} \item{filter}{(\code{logical(1)})\cr Whether the \code{\link[=ParamSet]{ParamSet()}} should be reduced to the space of the given Param Values. Note that in case of \code{use.defaults = TRUE} the filtering will be conducted after the insertion of the default values. Default is \code{FALSE}.} } \value{ \code{logical(1)}. } \description{ Check if a parameter value satisfies the constraints of the parameter description. This includes the \code{requires} expressions and the \code{forbidden} expression, if \code{par} is a \code{\link[=ParamSet]{ParamSet()}}. If \code{requires} is not satisfied, the parameter value must be set to scalar \code{NA} to be still feasible, a single scalar even in a case of a vector parameter. If the result is \code{FALSE} the attribute \code{"warning"} is attached which gives the reason for the negative result. If the parameter has \code{cnames}, these are also checked. } \examples{ p = makeNumericParam("x", lower = -1, upper = 1) isFeasible(p, 0) # True isFeasible(p, 2) # False, out of bounds isFeasible(p, "a") # False, wrong type # now for parameter sets ps = makeParamSet( makeNumericParam("x", lower = -1, upper = 1), makeDiscreteParam("y", values = c("a", "b")) ) isFeasible(ps, list(0, "a")) # True isFeasible(ps, list("a", 0)) # False, wrong order } ParamHelpers/man/getDefaults.Rd0000644000176000001440000000334213633666270016214 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/getDefaults.R \name{getDefaults} \alias{getDefaults} \title{Return defaults of parameters in parameter set.} \usage{ getDefaults(obj, include.null = FALSE, dict = NULL) } \arguments{ \item{obj}{(\code{\link[=Param]{Param()}} | \code{\link[=ParamSet]{ParamSet()}} | \code{list})\cr Parameter, parameter set or list of parameters, whose defaults should be extracted. In case the default values contain expressions, they will be evaluated using the provided dictionary (\code{dict}).} \item{include.null}{(\code{logical(1)})\cr Include \code{NULL} entries for parameters without default values in the result list? Note that this can be slightly dangerous as \code{NULL} might be used as default value for other parameters. Default is \code{FALSE}.} \item{dict}{(\code{environment} | \link{list} | \code{NULL})\cr Environment or list which will be used for evaluating the variables of expressions within a parameter, parameter set or list of parameters. The default is \code{NULL}.} } \value{ named \code{list}. Named (and in case of a \code{\link[=ParamSet]{ParamSet()}}, in the same order). Parameters without defaults are not present in the list. } \description{ Return defaults of single parameters or parameters in a parameter set or a list of parameters. } \examples{ ps1 = makeParamSet( makeDiscreteParam("x", values = c("a", "b"), default = "a"), makeNumericVectorParam("y", len = 2), makeIntegerParam("z", default = 99) ) getDefaults(ps1, include.null = TRUE) ps2 = makeParamSet( makeNumericVectorParam("a", len = expression(k), default = expression(p)), makeIntegerParam("b", default = 99), makeLogicalParam("c") ) getDefaults(ps2, dict = list(k = 3, p = 5.4)) } ParamHelpers/man/checkParamSet.Rd0000644000176000001440000000225213633666270016456 0ustar ripleyusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/checkParamSet.R \name{checkParamSet} \alias{checkParamSet} \title{Sanity check expressions of a parameter set.} \usage{ checkParamSet(par.set, dict = NULL) } \arguments{ \item{par.set}{\link{ParamSet}\cr Parameter set.} \item{dict}{(\code{environment} | \link{list} | \code{NULL})\cr Environment or list which will be used for evaluating the variables of expressions within a parameter, parameter set or list of parameters. The default is \code{NULL}.} } \value{ \code{\link{TRUE}} on success. An exception is raised otherwise. } \description{ Checks whether the default values of the numerical parameters are located within the corresponding boundaries. In case of discrete parameters it checks whether the values are a subset of the parameter's possible values. } \examples{ ps = makeParamSet( makeNumericParam("u", lower = expression(p)), makeIntegerParam("v", lower = 1, upper = expression(3 * p)), makeDiscreteParam("w", default = expression(z), values = c("a", "b")), makeDiscreteParam("x", default = "a", values = c("a", "b")), keys = c("p", "z") ) checkParamSet(ps, dict = list(p = 3, z = "b")) } ParamHelpers/DESCRIPTION0000644000176000001440000000474314260547430014410 0ustar ripleyusersPackage: ParamHelpers Title: Helpers for Parameters in Black-Box Optimization, Tuning and Machine Learning Version: 1.14.1 Authors@R: c(person(given = "Bernd", family = "Bischl", role = "aut", email = "bernd_bischl@gmx.net", comment = c(ORCID = "0000-0001-6002-6980")), person(given = "Michel", family = "Lang", role = "aut", email = "michellang@gmail.com", comment = c(ORCID = "0000-0001-9754-0393")), person(given = "Jakob", family = "Richter", role = c("cre", "aut"), email = "code@jakob-r.de", comment = c(ORCID = "0000-0003-4481-5554")), person(given = "Jakob", family = "Bossek", role = "aut", email = "j.bossek@gmail.com"), person(given = "Daniel", family = "Horn", role = "aut", email = "daniel.horn@tu-dortmund.de"), person(given = "Karin", family = "Schork", role = "ctb", email = "karin.schork@tu-dortmund.de"), person(given = "Pascal", family = "Kerschke", role = "aut", email = "kerschke@uni-muenster.de")) Description: Functions for parameter descriptions and operations in black-box optimization, tuning and machine learning. Parameters can be described (type, constraints, defaults, etc.), combined to parameter sets and can in general be programmed on. A useful OptPath object (archive) to log function evaluations is also provided. License: BSD_2_clause + file LICENSE URL: https://paramhelpers.mlr-org.com, https://github.com/mlr-org/ParamHelpers BugReports: https://github.com/mlr-org/ParamHelpers/issues Imports: backports, BBmisc (>= 1.10), checkmate (>= 1.8.2), fastmatch, methods Suggests: interp, covr, eaf, emoa, GGally, ggplot2, grid, gridExtra, irace (>= 2.1), lhs, plyr, reshape2, testthat ByteCompile: yes Encoding: UTF-8 RoxygenNote: 7.1.0 NeedsCompilation: yes Packaged: 2022-07-04 09:34:57 UTC; ripley Author: Bernd Bischl [aut] (), Michel Lang [aut] (), Jakob Richter [cre, aut] (), Jakob Bossek [aut], Daniel Horn [aut], Karin Schork [ctb], Pascal Kerschke [aut] Maintainer: Jakob Richter Repository: CRAN Date/Publication: 2022-07-04 11:29:28 UTC ParamHelpers/tests/0000755000176000001440000000000013164130622014025 5ustar ripleyusersParamHelpers/tests/testthat/0000755000176000001440000000000013636346430015677 5ustar ripleyusersParamHelpers/tests/testthat/test_getRequirements.R0000644000176000001440000000114413633666270022250 0ustar ripleyuserscontext("getRequirements") test_that("getRequirements", { ps = makeParamSet() # FIXME: BBmisc::namedList still buggy, only return list() xs = setNames(list(), character(0L)) expect_equal(getRequirements(ps), xs) r1 = quote(a == 1) r2 = quote(a == 2) ps = makeParamSet( makeIntegerParam("a", default = 1L), makeIntegerParam("b", default = 1L, requires = r1), makeNumericParam("c", default = 1L, requires = r2) ) expect_equal(getRequirements(ps, remove.null = TRUE), list(b = r1, c = r2)) expect_equal(getRequirements(ps, remove.null = FALSE), list(a = NULL, b = r1, c = r2)) }) ParamHelpers/tests/testthat/test_getParamTypeCounts.R0000644000176000001440000000150613164130622022647 0ustar ripleyuserscontext("getParamTypeCounts") test_that("getParamTypeCounts", { checkNonOccuringTypes = function(or, par.set) { sapply(setdiff(getTypeStringsAll(), getParamTypes(par.set)), function(type) { expect_equal(or[[type]], 0L) }) } par.set = makeParamSet() checkNonOccuringTypes(getParamTypeCounts(par.set), par.set) par.set = makeParamSet( makeNumericParam("numeric1", lower = 0L, upper = 10L), makeIntegerParam("integer1", lower = 0L, upper = 5L), makeIntegerParam("integer2", lower = 0L, upper = 5L), makeDiscreteParam("discrete1", values = letters[1:5]), makeCharacterParam("character1") ) or = getParamTypeCounts(par.set) expect_equal(or$numeric, 1L) expect_equal(or$integer, 2L) expect_equal(or$discrete, 1L) expect_equal(or$character, 1L) checkNonOccuringTypes(or, par.set) }) ParamHelpers/tests/testthat/test_convertParamSetToIrace.R0000644000176000001440000000754613636346430023461 0ustar ripleyuserscontext("convertParamSetToIrace") test_that("convertParamSetToIrace", { skip_on_cran() # FIXME: Delete if IRACE checks on R 3.6 --as-cran skip_if_not_installed("irace", minimum_version = "3.3.1") requirePackages("_irace") runIrace = function(ps, target.runner, max.exps = 10) { ip = convertParamSetToIrace(ps) expect_equal(getParamIds(ps, repeated = TRUE, with.nr = TRUE), as.character(ip$names)) res = capture.output( irace::irace( scenario = list( targetRunner = target.runner, instances = 1:10, maxExperiments = max.exps, logFile = tempfile() ), parameters = ip ) ) } ps = makeParamSet( makeLogicalParam("v1"), makeNumericParam("x1", lower = 1, upper = 4), makeIntegerParam("y1", lower = 1, upper = 4), makeDiscreteParam("z1", values = c("a", "b", "c")), makeLogicalVectorParam("v2", len = 2), makeNumericVectorParam("x2", len = 2, lower = 1:2, upper = pi), makeIntegerVectorParam("y2", len = 2, lower = 0:1, upper = 4), makeDiscreteVectorParam("z2", len = 2, values = c("a", "b", "c")) ) target.runner = function(experiment, config = list()) list(cost = 1) runIrace(ps, target.runner, max.exps = 300) ps = makeParamSet( makeDiscreteParam("x1", values = c("a", "b")), makeLogicalParam("x2", requires = quote(x1 == "a")), makeLogicalParam("x3", requires = quote(x1 == "a" && x2 == "FALSE" && x1 == "a" && x2 == "FALSE" && x1 == "a" && x2 == "FALSE" && x1 == "a" && x2 == "FALSE" && x1 == "a" && x2 == "FALSE" && x1 == "a" && x2 == "FALSE" && x1 == "a" && x2 == "FALSE" && x1 == "a" && x2 == "FALSE" && x1 == "a" && x2 == "FALSE" && x1 == "a" && x2 == "FALSE" && x1 == "a" && x2 == "FALSE" && x1 == "a" && x2 == "FALSE" && x1 == "a" && x2 == "FALSE" && x1 == "a" && x2 == "FALSE" && x1 == "a" && x2 == "FALSE" && x1 == "a" && x2 == "FALSE" && x1 == "a" && x2 == "FALSE" && x1 == "a" && x2 == "FALSE" && x1 == "a" && x2 == "FALSE" && x1 == "a" && x2 == "FALSE" && x1 == "a" && x2 == "FALSE")) ) ips = convertParamSetToIrace(ps) expect_false(identical(ips$constraints$x2, expression(TRUE))) target.runner = function(experiment, config = list()) { v = experiment$configuration if ((v$x1 == "a" && is.na(v$x2)) || (v$x1 == "b" && !is.na(v$x2))) { stop("foo") } if ((v$x1 == "a" && v$x2 == "FALSE" && is.na(v$x3)) || (!(v$x1 == "a" && v$x2 == "FALSE") && !is.na(v$x3))) { stop("requires failed") } list(cost = 1) } runIrace(ps, target.runner, max.exps = 300) }) test_that("convertParamSetToIrace checks box constraints", { ps = makeParamSet( makeIntegerLearnerParam(id = "i", lower = 1L) ) expect_error(convertParamSetToIrace(ps), "finite box") }) test_that("convertParamSetToIrace uses correct boundaries", { ps = makeParamSet( makeDiscreteParam("kernel", values = c("vanilladot", "rbfdot")), makeNumericParam("sigma", lower = 4e-9, upper = 2.123456724252662), makeIntegerParam("myInt", lower = 3, upper = 20), makeLogicalParam("Binar", default = TRUE) ) ips = convertParamSetToIrace(ps) expect_identical(vcapply(ips$domain, function(x) class(x)), c(kernel = "character", sigma = "numeric", myInt = "numeric", Binar = "character")) expect_identical(ips$boundary$sigma, as.numeric(unlist(ps$pars$sigma[c("lower", "upper")]))) expect_identical(ips$boundary$myInt, as.integer(unlist(ps$pars$myInt[c("lower", "upper")]))) }) test_that("convertParamSetToIrace work with vecparam", { # has issue here, see 85 ps = makeParamSet( makeNumericVectorParam("a", len = 2, -10, 10), makeDiscreteParam("b", c("v", "w")), makeNumericVectorParam("c", len = 2, -10, 10) ) i = convertParamSetToIrace(ps) b = i$domain expect_equal(b$a1, c(-10, 10)) expect_equal(b$a2, c(-10, 10)) expect_equal(b$b, c("v", "w")) expect_equal(b$c1, c(-10, 10)) expect_equal(b$c2, c(-10, 10)) }) ParamHelpers/tests/testthat/test_forbidden.R0000644000176000001440000000142613633666270021024 0ustar ripleyuserscontext("forbidden") test_that("forbidden", { ps = makeParamSet( makeNumericParam("x", lower = 1, upper = 5), makeIntegerParam("y", lower = 1, upper = 10), makeLogicalParam("z"), forbidden = quote(x > 2) ) expect_true(!isForbidden(ps, list(x = 1, y = 7, z = TRUE))) expect_true(isForbidden(ps, list(x = 3, y = 7, z = TRUE))) expect_true(isFeasible(ps, list(x = 1, y = 7, z = TRUE))) expect_true(!isFeasible(ps, list(x = 3, y = 7, z = TRUE))) xs = sampleValues(ps, 1000) fb = sapply(xs, isForbidden, par.set = ps) expect_true(!any(fb)) ok = sapply(xs, isFeasible, par = ps) expect_true(all(ok)) d = generateGridDesign(ps, resolution = 10) expect_true(all(d$x <= 2)) d = generateDesign(500, ps, augment = 100) expect_true(all(d$x <= 2)) }) ParamHelpers/tests/testthat/test_generateDesignOfDefaults.R0000644000176000001440000000720213633666270023767 0ustar ripleyuserscontext("generateDesignOfDefaults") test_that("generateDesignOfDefaults", { ps = makeParamSet( makeNumericParam("x", lower = 1, upper = 5, default = 1), makeIntegerParam("y", lower = 2, upper = 6, default = 3) ) d = generateDesignOfDefaults(ps) e = data.frame(x = 1, y = 3) attr(e, "trafo") = FALSE expect_equal(d, e) ps = makeParamSet( makeNumericParam("u", lower = 1, upper = 5, default = 1), makeIntegerParam("v", lower = 2, upper = 6, default = 3), makeLogicalParam("w", default = TRUE), makeDiscreteParam("x", values = c("a", "b"), default = "a") ) d = generateDesignOfDefaults(ps) e = data.frame(u = 1, v = 3, w = TRUE, x = factor("a", levels = c("a", "b"))) attr(e, "trafo") = FALSE expect_equal(d, e) # vectors ps = makeParamSet( makeNumericVectorParam("x", len = 2L, lower = 1, upper = 2, default = c(1, 2)), makeIntegerVectorParam("y", len = 2L, lower = 3, upper = 4, default = c(3, 3)), makeLogicalVectorParam("z", len = 2L, default = c(TRUE, FALSE)) ) d = generateDesignOfDefaults(ps) e = data.frame(x1 = 1, x2 = 2, y1 = 3, y2 = 3, z1 = TRUE, z2 = FALSE) attr(e, "trafo") = FALSE expect_equal(d, e) # trafo ps = makeParamSet( makeNumericParam("x", lower = 0, upper = 1, default = 0), makeNumericParam("y", lower = 3, upper = 4, trafo = function(x) 2 * x, default = 3) ) d = generateDesignOfDefaults(ps, trafo = TRUE) e = data.frame(x = 0, y = 6) attr(e, "trafo") = TRUE expect_equal(d, e) # missing default ps = makeParamSet( makeNumericParam("x", lower = 1, upper = 5), makeIntegerParam("y", lower = 2, upper = 6, default = 3) ) expect_error(generateDesignOfDefaults(ps), regexp = "No default parameter setting for: x") # dependent parameter spaces ps = makeParamSet( makeNumericParam("x", lower = 1, upper = 3, default = 2), makeNumericParam("y", lower = 1, upper = 3, default = 1, requires = quote(x > 2)) ) d = generateDesignOfDefaults(ps) e = data.frame(x = 2, y = NA_real_) attr(e, "trafo") = FALSE expect_equal(d, e) # correct type ps = makeParamSet( makeIntegerParam("x", lower = 1L, upper = 3L, default = 2) ) d = generateDesignOfDefaults(ps) e = data.frame(x = 2L) attr(e, "trafo") = FALSE expect_identical(class(d[, 1]), class(e[, 1])) # special vals ps = makeParamSet( makeNumericParam(id = "x1", lower = 0, upper = 2, default = "BLA", special.vals = list("BLA")), makeNumericParam(id = "x2", lower = 0, upper = 2, default = iris, special.vals = list(iris)) ) expect_error(generateDesignOfDefaults(ps), regexp = "special.vals as default for Parameter(s): x1,x2", fixed = TRUE) }) test_that("generateDesignOfDefaults works with discrete params and complex values", { ps = makeParamSet( makeDiscreteParam("p", values = c("a", "b"), default = "b") ) d = generateDesignOfDefaults(ps) expect_equal(d, data.frame(p = factor("b", levels = c("a", "b"))), check.attributes = FALSE) ps = makeParamSet( makeDiscreteParam("p", values = c(ir = "ir", foo = "bar"), default = "ir") ) d = generateDesignOfDefaults(ps) expect_equal(d, data.frame(p = factor("ir", levels = c("ir", "foo"))), check.attributes = FALSE) p = makeDiscreteParam("p", values = c(ir = "ir", foo = "bar"), default = "bar") ps = makeParamSet(p) d = generateDesignOfDefaults(ps) expect_equal(d, data.frame(p = factor("foo", levels = c("ir", "foo"))), check.attributes = FALSE) p = makeDiscreteParam("p", values = list(ir = "ir", foo = iris), default = iris) ps = makeParamSet(p) d = generateDesignOfDefaults(ps) expect_equal(d, data.frame(p = factor("foo", levels = c("ir", "foo"))), check.attributes = FALSE) }) ParamHelpers/tests/testthat/test_hasFiniteBoxConstraints.R0000644000176000001440000000225713200424217023665 0ustar ripleyuserscontext("hasFiniteBoxConstraints") test_that("hasFiniteBoxConstraints", { par = makeParamSet() expect_true(hasFiniteBoxConstraints(par)) par = makeNumericParam("x") expect_false(hasFiniteBoxConstraints(par)) par = makeNumericParam("x", lower = -10, upper = 10) expect_true(hasFiniteBoxConstraints(par)) par = makeNumericParam("x", lower = 0, upper = expression(n)) expect_true(hasFiniteBoxConstraints(par, dict = list(n = 10))) expect_false(hasFiniteBoxConstraints(par, dict = list(n = Inf))) par.set = makeParamSet( makeNumericParam("numeric1", lower = -100, upper = 100), makeIntegerParam("integer1", lower = 0L, upper = 15L) ) par.set = makeParamSet( makeNumericParam("numeric1", lower = -100, upper = 100), makeIntegerParam("integer1", lower = 0L, upper = 15L), makeDiscreteParam("discrete1", values = letters[1:2]), makeIntegerParam("integer2") ) expect_false(hasFiniteBoxConstraints(par.set)) par.set = makeParamSet( makeNumericParam("numeric1", lower = 1, upper = expression(n)) ) expect_true(hasFiniteBoxConstraints(par.set, dict = list(n = 10))) expect_false(hasFiniteBoxConstraints(par.set, dict = list(n = Inf))) }) ParamHelpers/tests/testthat/test_isFeasible.R0000644000176000001440000001401313633666270021132 0ustar ripleyuserscontext("isFeasible") test_that("isFeasible ParamSet", { ps = makeParamSet( makeIntegerParam("a", default = 1L), makeDiscreteParam("b", values = list("0" = "NIL", "1" = "ONE", "f" = function(x) x + 1)), makeIntegerParam("c", default = 1L, requires = quote(a == 1)), makeIntegerParam("d", default = 1L, requires = quote(a == 2)), makeIntegerParam("e", default = expression(n = 99L)), keys = "n" ) expect_true(isFeasible(ps, list(a = 1, b = function(x) x + 1, c = 1, d = NA, e = 12L))) expect_true(isFeasible(ps, list(a = 1, b = function(x) x + 1, c = 1), filter = TRUE)) expect_true(isFeasible(ps, list(a = 2, b = function(x) x + 1, d = 1), filter = TRUE)) expect_error(isFeasible(ps, list(a = 1, c = 1)), "does not match ParamSet length") expect_error(isFeasible(ps, list(1, 1)), "does not match ParamSet length") expect_error(isFeasible(ps, list(1, 1), filter = TRUE), "only works with named input") expect_error(isFeasible(ps, list(a = 1, zzz = 1), filter = TRUE), "zzz") expect_false((res = isFeasible(ps, list(a = 1, c = "1"), filter = TRUE))) expect_match(attr(res, "warning"), "c=1 does not meet constraints") expect_error(isFeasible(ps, list(c = 2), filter = TRUE), "needed for requirements: a") expect_false((res = isFeasible(ps, list(a = 2, c = 2), filter = TRUE))) expect_match(attr(res, "warning"), "Param c=2 is set but does not meet requirements") expect_true((res = isFeasible(ps, list(a = 2, c = NA), filter = TRUE))) expect_true(isFeasible(ps, list(c = 2), filter = TRUE, use.defaults = TRUE)) # make sure we can ignore defaults if they contradict a new setting ps = makeParamSet( makeIntegerParam("a", default = 1L, requires = quote(b == 2)), makeIntegerParam("b", default = 2L, requires = quote(c == TRUE)), makeLogicalParam("c", default = TRUE)) expect_error(isFeasible(ps, list(b = 3), filter = TRUE), "needed for requirements: c") expect_true(isFeasible(ps, list(b = 3), filter = TRUE, use.defaults = TRUE)) }) test_that("isFeasible LearnerParamSet", { ps = makeParamSet( makeIntegerLearnerParam("a", default = 1L), makeDiscreteLearnerParam("b", values = list("0" = "NIL", "1" = "ONE", "f" = function(x) x + 1)), makeIntegerLearnerParam("c", default = 1L, requires = quote(a == 1)), makeIntegerLearnerParam("d", default = 1L, requires = quote(a == 2)) ) expect_true(isFeasible(ps, list(a = 1, b = function(x) x + 1, c = 1, d = NA))) expect_true(isFeasible(ps, list(a = 1, b = function(x) x + 1, c = 1), filter = TRUE)) expect_true(isFeasible(ps, list(a = 2, b = function(x) x + 1, d = 1), filter = TRUE)) expect_error(isFeasible(ps, list(a = 1, c = 1)), "does not match ParamSet length") expect_error(isFeasible(ps, list(1, 1)), "does not match ParamSet length") expect_error(isFeasible(ps, list(1, 1), filter = TRUE), "only works with named input") expect_error(isFeasible(ps, list(a = 1, zzz = 1), filter = TRUE), "zzz") expect_false((res = isFeasible(ps, list(a = 1, c = "1"), filter = TRUE))) expect_match(attr(res, "warning"), "c=1 does not meet constraints") expect_error(isFeasible(ps, list(c = 2), filter = TRUE), "needed for requirements: a") expect_false((res = isFeasible(ps, list(a = 2, c = 2), filter = TRUE))) expect_match(attr(res, "warning"), "Param c=2 is set but does not meet requirements") expect_true((res = isFeasible(ps, list(a = 2, c = NA), filter = TRUE))) expect_true(isFeasible(ps, list(c = 2), filter = TRUE, use.defaults = TRUE)) ps = makeParamSet( makeIntegerLearnerParam("a", default = 1L), makeDiscreteLearnerParam("b", values = list("0" = "NIL", "1" = "ONE", "f" = function(x) x + 1)), makeIntegerLearnerParam("c", default = 1L, requires = quote(a == 1)), makeIntegerLearnerParam("d", default = 1L, requires = quote(a == 2)), makeIntegerLearnerParam("e", default = expression(n), upper = expression(2 * n)), keys = "n" ) expect_true(isFeasible(ps, list(a = 1, b = function(x) x + 1, c = 1, d = NA, e = 12L))) expect_true(isFeasible(ps, list(a = 1, b = function(x) x + 1, c = 1), filter = TRUE)) expect_true(isFeasible(ps, list(a = 2, b = function(x) x + 1, d = 1), filter = TRUE)) expect_error(isFeasible(ps, list(a = 1, c = 1)), "does not match ParamSet length") expect_error(isFeasible(ps, list(1, 1)), "does not match ParamSet length") expect_error(isFeasible(ps, list(1, 1), filter = TRUE), "only works with named input") expect_error(isFeasible(ps, list(a = 1, zzz = 1), filter = TRUE), "zzz") expect_false((res = isFeasible(ps, list(a = 1, c = "1"), filter = TRUE))) expect_match(attr(res, "warning"), "c=1 does not meet constraints") expect_error(isFeasible(ps, list(c = 2), filter = TRUE), "needed for requirements: a") expect_false((res = isFeasible(ps, list(a = 2, c = 2), filter = TRUE))) expect_match(attr(res, "warning"), "Param c=2 is set but does not meet requirements") expect_true((res = isFeasible(ps, list(a = 2, c = NA), filter = TRUE))) }) test_that("length of vectors", { ps = makeParamSet( makeIntegerVectorLearnerParam("a", default = 1L), makeNumericVectorLearnerParam("b", len = expression(n)), makeNumericVectorLearnerParam("c", len = 4L, lower = -1, upper = 5), keys = "n" ) expect_true(isFeasible(ps, list(a = 1, b = 2, c = rep(3, 4)))) expect_false((res = isFeasible(ps, list(a = 1, b = 2, c = 3)))) expect_match(attr(res, "warning"), "The parameter setting c=3 does not meet constraints") }) # we had a bug here, see issue #145 test_that("isFeasible works when len=NA, and default is given (with other lengths than in isFeasible)", { p = makeIntegerVectorLearnerParam(id = "test", default = c(10, 10), lower = 0) expect_true(isFeasible(p, c(10, 10, 10))) expect_false(isFeasible(p, c(-1))) }) test_that("atomic requires", { ps = makeParamSet( makeLogicalParam("a"), makeIntegerParam("b", 0, 1, requires = quote(a)) ) expect_true(isFeasible(ps, list(a = TRUE, b = 0))) expect_true(isFeasible(ps, list(a = FALSE, b = NA))) expect_false(isFeasible(ps, list(a = TRUE, b = NA))) expect_false(isFeasible(ps, list(a = FALSE, b = 0))) }) ParamHelpers/tests/testthat/test_Param.R0000644000176000001440000002500513633666270020127 0ustar ripleyuserscontext("Parameter") test_that("num param", { p = makeNumericParam(id = "x", lower = -1L, upper = 1) expect_equal("numeric", p$type) expect_equal(-1, p$lower) expect_equal(1, p$upper) expect_true(isFeasible(p, -1)) expect_true(isFeasible(p, 1)) expect_true(isFeasible(p, 0)) expect_true(!isFeasible(p, 2)) expect_true(!isFeasible(p, Inf)) expect_true(!isFeasible(p, -Inf)) expect_true(!isFeasible(p, NA)) expect_true(!isFeasible(p, "bam")) p = makeNumericParam(id = "x", lower = 0, upper = Inf, special.vals = list(NA_real_, function(x) x + 1, matrix())) expect_true(isFeasible(p, 2)) expect_true(!isFeasible(p, -2)) expect_true(!isFeasible(p, -Inf)) expect_true(!isFeasible(p, NULL)) expect_true(isFeasible(p, NA_real_)) expect_true(isFeasible(p, function(x) x + 1)) expect_true(isFeasible(p, matrix())) expect_equal(p$values, NULL) # defaults p = makeNumericParam(id = "x", allow.inf = TRUE, default = Inf) expect_error(makeNumericParam(id = "x", allow.inf = FALSE, default = Inf), "feasible") ## Error conditions: expect_error(makeNumericParam(id = "x", lower = "bam", upper = 1)) expect_error(makeNumericParam(id = "x", lower = NA, upper = 1)) expect_error(makeNumericParam(id = "x", lower = NULL, upper = 1)) expect_error(makeNumericParam(id = "x", lower = 0, upper = "bam")) expect_error(makeNumericParam(id = "x", lower = 0, upper = NA)) expect_error(makeNumericParam(id = "x", lower = 0, upper = NULL)) expect_error(makeNumericParam(id = "x", lower = 1, upper = -1)) expect_error(makeNumericParam(id = "x", lower = c(-1, 1), upper = 2)) expect_error(makeNumericParam(id = "x", lower = -1, upper = c(1, 2))) }) test_that("num vec param", { p = makeNumericVectorParam(id = "x", lower = -1L, upper = 1, len = 2) expect_equal("numericvector", p$type) expect_equal(c(-1, -1), p$lower) expect_equal(c(1, 1), p$upper) expect_true(isFeasible(p, c(-1, -1))) expect_true(isFeasible(p, c(1, 1))) expect_true(isFeasible(p, c(0, 1))) expect_true(!isFeasible(p, c(2, 0))) expect_true(!isFeasible(p, c(NA, 0))) expect_true(!isFeasible(p, Inf)) expect_true(!isFeasible(p, -Inf)) expect_true(!isFeasible(p, NA)) expect_true(!isFeasible(p, "bam")) p = makeNumericVectorParam(id = "x", lower = 0, upper = Inf, len = 3, special.vals = list(-Inf)) expect_true(isFeasible(p, c(2, 1, 1))) expect_true(!isFeasible(p, c(-2, 1, 0))) expect_true(!isFeasible(p, c(-Inf, 1))) expect_true(!isFeasible(p, NULL)) expect_true(isFeasible(p, -Inf)) ## Error conditions: expect_error(makeNumericVectorParam(id = "x", lower = "bam", upper = 1)) expect_error(makeNumericVectorParam(id = "x", len = 2, lower = NA, upper = 1)) expect_error(makeNumericVectorParam(id = "x", len = 2, lower = NULL, upper = 1)) expect_error(makeNumericVectorParam(id = "x", len = 2, lower = 0, upper = "bam")) expect_error(makeNumericVectorParam(id = "x", len = 2, lower = 0, upper = NA)) expect_error(makeNumericVectorParam(id = "x", len = 2, lower = 0, upper = NULL)) expect_error(makeNumericVectorParam(id = "x", len = 2, lower = 1, upper = -1)) expect_error(makeNumericVectorParam(id = "x", len = 2, lower = c(1, 1), upper = c(0, 0))) }) test_that("int param", { p = makeIntegerParam(id = "x", lower = -1L, upper = 1) expect_equal("integer", p$type) expect_equal(-1, p$lower) expect_equal(1, p$upper) expect_true(isFeasible(p, -1)) expect_true(isFeasible(p, -1L)) expect_true(isFeasible(p, 1L)) expect_true(isFeasible(p, 0L)) expect_true(!isFeasible(p, 0.5)) expect_true(!isFeasible(p, Inf)) expect_true(!isFeasible(p, -Inf)) expect_true(!isFeasible(p, NA)) expect_true(!isFeasible(p, "bam")) p = makeIntegerParam(id = "x", lower = 0) expect_true(isFeasible(p, 2L)) expect_true(!isFeasible(p, Inf)) expect_true(!isFeasible(p, -2L)) expect_true(!isFeasible(p, -Inf)) expect_true(!isFeasible(p, NULL)) ## Error conditions: expect_error(makeIntegerParam(id = "x", lower = "bam", upper = 1L)) expect_error(makeIntegerParam(id = "x", lower = NA, upper = 1L)) expect_error(makeIntegerParam(id = "x", lower = NULL, upper = 1L)) expect_error(makeIntegerParam(id = "x", lower = 0L, upper = "bam")) expect_error(makeIntegerParam(id = "x", lower = 0L, upper = NA)) expect_error(makeIntegerParam(id = "x", lower = 0L, upper = NULL)) expect_error(makeIntegerParam(id = "x", lower = 1L, upper = -1L)) expect_error(makeIntegerParam(id = "x", lower = c(-1L, 1L), upper = 2L)) expect_error(makeIntegerParam(id = "x", lower = -1L, upper = c(1L, 2L))) }) test_that("int vec param", { p = makeIntegerVectorParam(id = "x", lower = -10L, upper = 10, len = 2) expect_equal("integervector", p$type) expect_equal(c(-10, -10), p$lower) expect_equal(c(10, 10), p$upper) expect_true(isFeasible(p, c(-10, -1))) expect_true(isFeasible(p, c(1, 1))) expect_true(isFeasible(p, c(0, 10))) expect_true(!isFeasible(p, c(20, 0))) expect_true(!isFeasible(p, Inf)) expect_true(!isFeasible(p, -Inf)) expect_true(!isFeasible(p, c(NA, 5))) expect_true(!isFeasible(p, "bam")) p = makeIntegerVectorParam(id = "x", lower = 0, len = 3) expect_true(isFeasible(p, c(2, 1, 1))) expect_true(isFeasible(p, c(10^7, 10^7, 10^7))) expect_true(!isFeasible(p, c(-2, 1, 0))) expect_true(!isFeasible(p, c(-Inf, 1))) expect_true(!isFeasible(p, NULL)) ## Error conditions: expect_error(makeIntegerVectorParam(id = "x", lower = "bam", upper = 1)) expect_error(makeIntegerVectorParam(id = "x", len = 2, lower = NA, upper = 1)) expect_error(makeIntegerVectorParam(id = "x", len = 2, lower = NULL, upper = 1)) expect_error(makeIntegerVectorParam(id = "x", len = 2, lower = 0, upper = "bam")) expect_error(makeIntegerVectorParam(id = "x", len = 2, lower = 0, upper = NA)) expect_error(makeIntegerVectorParam(id = "x", len = 2, lower = 0, upper = NULL)) expect_error(makeIntegerVectorParam(id = "x", len = 2, lower = 1, upper = -1)) expect_error(makeIntegerVectorParam(id = "x", len = 2, lower = c(1, 1), upper = c(0, 0))) }) test_that("discrete param", { f = function(x) 2 * x p = makeDiscreteParam(id = "x", values = list(a = "char", b = 2L, c = 2.2, d = f, "e")) expect_equal("discrete", p$type) expect_true(isFeasible(p, "char")) expect_true(isFeasible(p, 2L)) expect_true(isFeasible(p, 2.2)) expect_true(isFeasible(p, f)) expect_true(isFeasible(p, "char")) expect_true(isFeasible(p, 2L)) expect_true(isFeasible(p, 2)) expect_true(isFeasible(p, 2.2)) expect_true(isFeasible(p, function(x) 2 * x)) expect_true(isFeasible(p, "e")) expect_true(!isFeasible(p, "a")) expect_true(!isFeasible(p, sum)) expect_true(!isFeasible(p, NULL)) expect_equal(p$lower, NULL) expect_equal(p$upper, NULL) ## Error conditions: expect_error(makeDiscreteParam(id = "x", values = list(a = 1, "a")), "names could not be guessed") expect_error(makeDiscreteParam(id = "x", values = list()), "No possible value") }) test_that("discrete vec param", { f = function(x) 2 * x p = makeDiscreteVectorParam(id = "x", len = 2, values = list(a = "char", b = 2L, c = 2.2, d = f, "e")) expect_equal("discretevector", p$type) expect_true(isFeasible(p, list("char", "char"))) expect_true(isFeasible(p, list("char", f))) expect_true(isFeasible(p, list(2.2, 2L))) expect_true(!isFeasible(p, list())) expect_true(!isFeasible(p, list("char"))) expect_true(!isFeasible(p, list("a", "b"))) expect_true(!isFeasible(p, list(NULL, NULL))) expect_equal(p$lower, NULL) expect_equal(p$upper, NULL) ## Error conditions: expect_error(makeDiscreteVectorParam(id = "x", len = 2, values = list(a = 1, "a")), "names could not be guessed") expect_error(makeDiscreteVectorParam(id = "x", len = 2, values = list()), "No possible value") }) test_that("logic param", { p = makeLogicalParam(id = "x") expect_equal("logical", p$type) expect_true(isFeasible(p, TRUE)) expect_true(isFeasible(p, FALSE)) expect_true(!isFeasible(p, "bam")) expect_true(!isFeasible(p, 1L)) expect_true(!isFeasible(p, 1)) expect_true(!isFeasible(p, NULL)) }) test_that("logic vec param", { p = makeLogicalVectorParam(id = "x", len = 2) expect_equal("logicalvector", p$type) expect_true(isFeasible(p, c(TRUE, FALSE))) expect_true(!isFeasible(p, "bam")) expect_true(!isFeasible(p, TRUE)) expect_true(!isFeasible(p, FALSE)) expect_true(!isFeasible(p, NULL)) }) test_that("character param", { p = makeCharacterParam(id = "s") expect_equal("character", p$type) expect_true(isFeasible(p, collapse(sample(letters, 5L)))) expect_true(!isFeasible(p, 1L)) expect_true(!isFeasible(p, 1)) expect_true(!isFeasible(p, NULL)) expect_true(!isFeasible(p, factor("bam"))) }) test_that("character vec param", { p = makeCharacterVectorParam(id = "x", len = 2) expect_equal("charactervector", p$type) expect_true(isFeasible(p, c("a", "b"))) expect_false(isFeasible(p, c(1, 1))) expect_false(isFeasible(p, "a")) expect_false(isFeasible(p, 1)) p = makeCharacterVectorParam(id = "x", len = 2, cnames = c("x1", "x2")) expect_equal("charactervector", p$type) expect_true(isFeasible(p, c(x1 = "a", x2 = "b"))) expect_false(isFeasible(p, c("a", "b"))) }) test_that("function param", { p = makeFunctionParam(id = "x") expect_equal("function", p$type) expect_true(isFeasible(p, identity)) expect_true(!isFeasible(p, "bam")) expect_true(!isFeasible(p, 1L)) expect_true(!isFeasible(p, 1)) expect_true(!isFeasible(p, NULL)) }) test_that("untyped param", { p = makeUntypedParam(id = "x") expect_equal("untyped", p$type) expect_true(isFeasible(p, 1)) expect_true(isFeasible(p, identity)) expect_true(isFeasible(p, NULL)) }) test_that("param print works", { p = makeNumericParam(id = "x", lower = -1L, upper = 1) expect_output(print(p), "numeric") p = makeUntypedParam(id = "x") expect_output(print(p), "untyped") p = makeUntypedParam(id = "x", default = NULL) expect_output(print(p), "untyped") p = makeUntypedParam(id = "x", default = 99) expect_output(print(p), "untyped") expect_output(print(p), "99") p = makeUntypedParam(id = "x", default = c(99, 99)) expect_output(print(p), "untyped") }) test_that("normal (not learner) vec param cannot have NA lengths", { expect_error(makeNumericVectorParam("x", len = NA)) expect_error(makeIntegerVectorParam("x", len = NA)) expect_error(makeDiscreteVectorParam("x", values = 1:2, len = NA)) }) test_that("for discrete: default setting cannot be the name but must the VALUE", { # should run p = makeDiscreteParam("p", values = c(foo = "bar"), default = "bar") # should run expect_error(makeDiscreteParam("p", values = c(foo = "bar"), default = "foo"), "feasible") }) ParamHelpers/tests/testthat/test_updateParVals.R0000644000176000001440000000311313633666270021636 0ustar ripleyuserscontext("updateParVals") test_that("updateParVals works", { # simple dependency pa = list(a = 1, b = 2, d = 4, e = 5) pb = list(a = 0, c = 3) ps = makeParamSet( makeIntegerParam("a"), makeIntegerParam("b", requires = quote(a == 1)), makeIntegerParam("c"), makeIntegerParam("d"), makeIntegerParam("e", requires = quote(f == TRUE)), makeLogicalParam("f", default = TRUE)) pc = updateParVals(ps, pa, pb) expect_equal(pc, list(a = 0, c = 3, d = 4, e = 5)) expect_warning(updateParVals(ps, pa, pb, warn = TRUE), "ParamSetting b=2") pb2 = list(a = 0, f = FALSE) pc2 = updateParVals(ps, pa, pb2) expect_equal(pc2, list(a = 0, f = FALSE, d = 4)) # sanity expect_equal(updateParVals(ps, pa, list()), pa) expect_equal(updateParVals(ps, list(), pb), pb) # chained dependency pa = list(a = 1, b = 2, c = 0.5, d = 4) pb = list(a = -3) ps = makeParamSet( makeIntegerParam("a", requires = quote(e == TRUE)), makeIntegerParam("b", requires = quote(a == 1)), makeNumericParam("c"), makeIntegerParam("d", requires = quote(b == 2)), makeLogicalParam("e", default = TRUE)) pc = updateParVals(ps, pa, pb) expect_equal(pc, list(a = -3, c = 0.5)) # chained dependency with defaults #maybe redundanant with pc2? ps = makeParamSet( makeIntegerParam("a", default = 1L, requires = quote(b == 2)), makeIntegerParam("b", default = 2L, requires = quote(c == TRUE)), makeLogicalParam("c", default = TRUE)) pa = list(a = 1, b = 2, c = TRUE) pb = list(b = 3) pc = updateParVals(ps, pa, pb) expect_equal(pc, list(b = 3, c = TRUE)) }) ParamHelpers/tests/testthat/test_paramValueToString.R0000644000176000001440000000505713633666270022663 0ustar ripleyuserscontext("paramValueToString") test_that("paramValueToString ", { u = makeNumericParam("u") v = makeIntegerVectorParam("v", len = 2) w = makeDiscreteParam("w", values = list(a = 1, b = list())) x = makeLogicalParam("x") y = makeLogicalVectorParam("y", len = 2) z = makeDiscreteVectorParam("z", len = 2, values = list(a = 1, b = list())) s = makeCharacterParam("s") p1 = makeUntypedParam("w", default = iris) p2 = makeLogicalParam("t", default = NULL, special.vals = list(NULL)) ps = makeParamSet(u, v, w, x, y, z, s) expect_equal(paramValueToString(u, 1), "1") expect_equal(paramValueToString(u, 1.2345), "1.23") expect_equal(paramValueToString(v, c(1, 2)), "1,2") expect_equal(paramValueToString(w, 1), "a") expect_equal(paramValueToString(w, list()), "b") expect_equal(paramValueToString(x, TRUE), "TRUE") expect_equal(paramValueToString(y, c(TRUE, FALSE)), "TRUE,FALSE") expect_equal(paramValueToString(z, list(1, 1)), "a,a") expect_equal(paramValueToString(z, list(1, list())), "a,b") expect_equal(paramValueToString(s, "PH"), "PH") expect_equal(paramValueToString(ps, list(u = 1, v = 1:2, w = list(), x = FALSE, y = c(TRUE, FALSE), z = list(1, list()), s = "PH")), "u=1; v=1,2; w=b; x=FALSE; y=TRUE,FALSE; z=a,b; s=PH") expect_equal(paramValueToString(u, expression(ceiling(n / 3))), "ceiling(n/3)") expect_equal(paramValueToString(p1, iris), "") expect_equal(paramValueToString(p2, NULL), "") }) test_that("requires works", { ps = makeParamSet( makeDiscreteParam("x", values = c("a", "b")), makeNumericParam("y", lower = 1, upper = 2, requires = quote(x == "a")), makeIntegerVectorParam("z", len = 2, lower = 1, upper = 20, requires = quote(x == "b")) ) expect_equal(paramValueToString(ps, list(x = "a", y = 1, z = NA), show.missing.values = TRUE), "x=a; y=1; z=NA") expect_equal(paramValueToString(ps, list(x = "b", y = NA, z = 2:3), show.missing.values = TRUE), "x=b; y=NA; z=2,3") expect_equal(paramValueToString(ps, list(x = "b", z = 2:3), show.missing.values = TRUE), "x=b; z=2,3") expect_equal(paramValueToString(ps, list(x = "a", y = 1, z = NA), show.missing.values = FALSE), "x=a; y=1") expect_equal(paramValueToString(ps, list(x = "b", y = NA, z = 2:3), show.missing.values = FALSE), "x=b; z=2,3") expect_equal(paramValueToString(ps, list(x = "b", z = 2:3), show.missing.values = FALSE), "x=b; z=2,3") }) test_that("num.format works", { x = makeNumericParam("x") expect_equal(paramValueToString(x, 1), "1") expect_equal(paramValueToString(x, 1, num.format = "%.3f"), "1.000") }) ParamHelpers/tests/testthat/test_OptPath.R0000644000176000001440000003652713636346430020455 0ustar ripleyuserscontext("OptPath") test_that("OptPath", { ps = makeParamSet( makeNumericParam("x"), makeDiscreteParam("y", values = c("a", "b")) ) op = makeOptPathDF(par.set = ps, y.names = c("z1", "z2"), minimize = c(TRUE, FALSE)) addOptPathEl(op, x = list(x = 1, y = "a"), y = c(z1 = 1, z2 = 4)) addOptPathEl(op, x = list(x = 2, y = "a"), y = c(z1 = 3, z2 = 2)) expect_equal(op$env$dob, 1:2) setOptPathElEOL(op, 2, 8) expect_equal(op$env$eol[2], 8) # test getters expect_equal(getOptPathX(op), data.frame(x = 1:2, y = factor("a", levels = c("a", "b")))) expect_equal(getOptPathX(op, dob = 2), data.frame(x = 2, y = factor("a", levels = c("a", "b")))) expect_equal(getOptPathY(op, "z1"), c(1, 3)) expect_equal(getOptPathY(op, "z2"), c(4, 2)) expect_equal(getOptPathY(op), matrix(c(1, 3, 4, 2), nrow = 2L, dimnames = list(1:2, c("z1", "z2")))) expect_equal(getOptPathY(op, "z2", drop = FALSE), matrix(c(4, 2), nrow = 2L, dimnames = list(1:2, c("z2")))) expect_equal(getOptPathY(op, "z2", drop = TRUE), c(4, 2)) expect_equal(getOptPathY(op, "z2"), c(4, 2)) expect_equal(getOptPathY(op, eol = 8), matrix(c(3, 2), nrow = 1L, dimnames = list(2, c("z1", "z2")))) expect_equal(getOptPathDOB(op), c(1, 2)) expect_equal(getOptPathEOL(op), c(NA, 8)) x = as.data.frame(op) expect_true(is.data.frame(x)) expect_equal(nrow(x), 2) expect_equal(ncol(x), 6) expect_equal(levels(x$y), getParamSetValues(ps)$y) expect_output(print(op), "Optimization path") expect_equal(getOptPathEl(op, 1)$x, list(x = 1, y = "a")) gbe = function(op, y.name, dob) { i = getOptPathBestIndex(op, y.name, dob) getOptPathEl(op, i) } expect_equal(gbe(op, y.name = "z1", dob = 1:2), getOptPathEl(op, 1)) expect_equal(gbe(op, y.name = "z2", dob = 1:2), getOptPathEl(op, 1)) expect_equal(gbe(op, y.name = "z1", dob = 1), getOptPathEl(op, 1)) expect_equal(gbe(op, y.name = "z2", dob = 1), getOptPathEl(op, 1)) expect_equal(gbe(op, y.name = "z1", dob = 2), getOptPathEl(op, 2)) expect_equal(gbe(op, y.name = "z2", dob = 2), getOptPathEl(op, 2)) setOptPathElDOB(op, 1, 1) setOptPathElDOB(op, 2, 3) expect_equal(as.data.frame(op)$dob, c(1, 3)) setOptPathElDOB(op, 1:2, 7) expect_equal(as.data.frame(op)$dob, c(7, 7)) setOptPathElDOB(op, 1:2, 4:5) expect_equal(as.data.frame(op)$dob, c(4, 5)) setOptPathElEOL(op, 1, 1) setOptPathElEOL(op, 2, 3) expect_equal(as.data.frame(op)$eol, c(1, 3)) setOptPathElEOL(op, 1:2, 7) expect_equal(as.data.frame(op)$eol, c(7, 7)) setOptPathElEOL(op, 1:2, 4:5) expect_equal(as.data.frame(op)$eol, c(4, 5)) ps = makeParamSet( makeNumericVectorParam("x", len = 2), makeIntegerParam("y") ) op = makeOptPathDF(par.set = ps, y.names = "z", minimize = TRUE) addOptPathEl(op, x = list(c(1, 1), 7L), y = 1) addOptPathEl(op, x = list(c(2, 2), 8L), y = 3) df = as.data.frame(op) expect_equal(dim(df), c(2, 3 + 1 + 2)) expect_equal(colnames(df), c("x1", "x2", "y", "z", "dob", "eol")) e = getOptPathEl(op, 1) expect_equal(e$x, list(x = c(1, 1), y = 7L)) # really make sure that names are there expect_equal(names(e$y), "z") # check error msg for wrong y expect_error(addOptPathEl(op, x = list(c(1, 1), 7L), y = c(1, 1)), "Must have length") }) test_that("OptPath with vector and discrete params works", { ps = makeParamSet( makeIntegerVectorParam("x0", len = 2), makeDiscreteParam("x1", values = c("a", "b")), makeDiscreteParam("x2", values = 1:2), makeDiscreteParam("x3", values = c(1.2, 5)), makeDiscreteParam("x4", values = list(foo = identity, bar = list())), makeLogicalParam("x5"), makeDiscreteVectorParam("x6", len = 2, values = list(a = identity, b = 1)), makeLogicalVectorParam("x7", len = 3), makeCharacterParam("x8") ) op = makeOptPathDF(par.set = ps, y.names = "y", minimize = TRUE) x = list(x0 = c(1L, 3L), x1 = "a", x2 = 2L, x3 = 5, x4 = identity, x5 = FALSE, x6 = list(b = 1, a = identity), x7 = c(TRUE, FALSE, TRUE), x8 = "PH") addOptPathEl(op, x = x, y = 0) d = as.data.frame(op) expect_true(nrow(d) == 1 && ncol(d) == 3 + 8 + 1 + 2 + 2) expect_true(is.integer(d$x01)) expect_true(is.integer(d$x02)) expect_true(is.factor(d$x1)) expect_true(is.factor(d$x2)) expect_true(is.factor(d$x3)) expect_true(is.factor(d$x4)) expect_true(is.logical(d$x5)) expect_true(is.factor(d$x61)) expect_true(is.factor(d$x62)) expect_true(is.logical(d$x71)) expect_true(is.logical(d$x72)) expect_true(is.logical(d$x73)) expect_true(is.factor(d$x8)) # strings internally saved as factors? expect_true( d[1, 1] == 1L && d[1, 2] == 3L && d[1, 3] == "a" && d[1, 4] == "2" && d[1, 5] == "5" && d[1, 6] == "foo" && d[1, 7] == FALSE && d[1, 8] == "b" && d[1, 9] == "a" && d[1, 10] == TRUE && d[1, 11] == FALSE && d[1, 12] == TRUE && d[1, 13] == "PH") d = as.data.frame(op, discretes.as.factor = TRUE) expect_true(nrow(d) == 1 && ncol(d) == 3 + 8 + 1 + 2 + 2) expect_true(is.integer(d$x01)) expect_true(is.integer(d$x02)) expect_true(is.factor(d$x1)) expect_true(is.factor(d$x2)) expect_true(is.factor(d$x3)) expect_true(is.factor(d$x4)) expect_true(is.logical(d$x5)) expect_true(is.factor(d$x61)) expect_true(is.factor(d$x62)) expect_true(is.logical(d$x71)) expect_true(is.logical(d$x72)) expect_true(is.logical(d$x73)) expect_true(is.factor(d$x8)) # strings internally saved as factors? expect_true( d[1, 1] == 1L && d[1, 2] == 3L && d[1, 3] == "a" && d[1, 4] == "2" && d[1, 5] == "5" && d[1, 6] == "foo" && d[1, 7] == FALSE && d[1, 8] == "b" && d[1, 9] == "a" && d[1, 10] == TRUE && d[1, 11] == FALSE && d[1, 12] == TRUE && d[1, 13] == "PH") e = getOptPathEl(op, 1L) expect_equal(e$x, x) }) test_that("getOptPathBestIndex tie-handling", { ps = makeParamSet( makeNumericParam("x") ) op = makeOptPathDF(par.set = ps, y.names = "y", minimize = TRUE) addOptPathEl(op, x = list(x = 0), y = 0) addOptPathEl(op, x = list(x = 0), y = 0) addOptPathEl(op, x = list(x = 0), y = 1) addOptPathEl(op, x = list(x = 0), y = 0) addOptPathEl(op, x = list(x = 0), y = 1) expect_equal(getOptPathBestIndex(op), 4L) expect_equal(getOptPathBestIndex(op, ties = "first"), 1L) expect_equal(getOptPathBestIndex(op, ties = "last"), 4L) expect_true(getOptPathBestIndex(op, ties = "random") %in% c(1L, 2L, 4L)) expect_equal(getOptPathBestIndex(op, ties = "all"), c(1L, 2L, 4L)) op = makeOptPathDF(par.set = ps, y.names = "y", minimize = FALSE) addOptPathEl(op, x = list(x = 0), y = 0) addOptPathEl(op, x = list(x = 0), y = 0) addOptPathEl(op, x = list(x = 0), y = 1) addOptPathEl(op, x = list(x = 0), y = 0) addOptPathEl(op, x = list(x = 0), y = 1) expect_equal(getOptPathBestIndex(op), 5L) expect_equal(getOptPathBestIndex(op, ties = "first"), 3L) expect_equal(getOptPathBestIndex(op, ties = "last"), 5L) expect_true(getOptPathBestIndex(op, ties = "random") %in% c(3L, 5L)) expect_equal(getOptPathBestIndex(op, ties = "all"), c(3L, 5L)) }) test_that("requires works", { ps = makeParamSet( makeDiscreteParam("x", values = c("a", "b")), makeNumericParam("y", lower = 1, upper = 2, requires = quote(x == "a")), makeIntegerVectorParam("z", len = 2, lower = 1, upper = 20, requires = quote(x == "b")) ) op = makeOptPathDF(par.set = ps, y.names = "foo", minimize = TRUE) el = list(x = "b", y = NA, z = 1:2) addOptPathEl(op, x = el, y = 0) # check that correct NAs are present expect_equal(op$env$path[, 2:4], data.frame(y = NA_real_, z1 = 1L, z2 = 2L)) op = makeOptPathDF(par.set = ps, y.names = "foo", minimize = TRUE) el = list(x = "a", y = 1, z = NA) addOptPathEl(op, x = el, y = 0) expect_equal(getOptPathEl(op, 1)$x, el) # check that correct NAs are present expect_equal(op$env$path[, 2:4], data.frame(y = 1, z1 = NA_integer_, z2 = NA_integer_)) el = list(x = "b", y = NA, z = c(2, 3)) addOptPathEl(op, x = el, y = 0) expect_equal(getOptPathEl(op, 2)$x, el) d = as.data.frame(op, discretes.as.factor = TRUE) expect_equal(d[, 1:4], data.frame(x = c("a", "b"), y = c(1, NA), z1 = c(NA, 2L), z2 = c(NA, 3L), stringsAsFactors = TRUE)) }) test_that("pareto front", { ps = makeParamSet(makeNumericParam("x")) op = makeOptPathDF(par.set = ps, y.names = c("y1", "y2"), minimize = c(TRUE, TRUE)) addOptPathEl(op, x = list(x = 3), y = c(9, 4)) f = getOptPathParetoFront(op, index = FALSE) expect_equal(f, matrix(c(9, 4), nrow = 1L, dimnames = list(1, c("y1", "y2")))) addOptPathEl(op, x = list(x = 4), y = c(4, 9)) addOptPathEl(op, x = list(x = 1), y = c(5, 3)) addOptPathEl(op, x = list(x = 2), y = c(2, 4)) f = getOptPathParetoFront(op, index = TRUE) expect_equal(f, 3:4) f = getOptPathParetoFront(op, index = FALSE) expect_equal(f, matrix(c(5, 2, 3, 4), nrow = 2L, dimnames = list(3:4, c("y1", "y2")))) f = getOptPathParetoFront(op, index = TRUE, dob = 3:4) expect_equal(f, 3:4) f = getOptPathParetoFront(op, index = FALSE, dob = 3:4) expect_equal(f, matrix(c(5, 2, 3, 4), nrow = 2L, dimnames = list(3:4, c("y1", "y2")))) op$minimize = c(TRUE, FALSE) f = getOptPathParetoFront(op, index = TRUE) expect_equal(f, c(2, 4)) }) test_that("error message and exec time works", { ps = makeParamSet(makeNumericParam("x")) op = makeOptPathDF(par.set = ps, y.names = "y", minimize = TRUE, include.error.message = TRUE) addOptPathEl(op, x = list(x = 1), y = 5) addOptPathEl(op, x = list(x = 2), y = 3) addOptPathEl(op, x = list(x = 3), y = 9) addOptPathEl(op, x = list(x = 4), y = 3, error.message = "bla") expect_equal(ncol(as.data.frame(op)), 5) errors = which(!is.na(getOptPathErrorMessages(op))) expect_equal("bla", getOptPathEl(op, errors)$error.message) ps = makeParamSet(makeNumericParam("x")) op = makeOptPathDF(par.set = ps, y.names = "y", minimize = TRUE, include.error.message = TRUE, include.exec.time = TRUE) addOptPathEl(op, x = list(x = 1), y = 5, exec.time = 2) addOptPathEl(op, x = list(x = 2), y = 3, exec.time = 2) addOptPathEl(op, x = list(x = 3), y = 9, exec.time = 3) addOptPathEl(op, x = list(x = 4), y = 3, exec.time = NA_real_, error.message = "bla") expect_equal(ncol(as.data.frame(op)), 6) errors = which(!is.na(getOptPathErrorMessages(op))) expect_equal("bla", getOptPathEl(op, errors)$error.message) expect_equal(getOptPathExecTimes(op), c(2, 2, 3, NA)) }) test_that("logging extra works", { ps = makeParamSet(makeNumericParam("v")) op = makeOptPathDF(par.set = ps, y.names = "y", minimize = TRUE, include.extra = TRUE) addOptPathEl(op, x = list(v = 1), y = 5, extra = list(ee = 7)) df = setRowNames(as.data.frame(op), NULL) expect_equal(df, data.frame(v = 1, y = 5, dob = 1L, eol = NA_integer_, ee = 7)) expect_equal(getOptPathEl(op, 1L), list(x = list(v = 1), y = c(y = 5), dob = 1L, eol = NA_integer_, extra = list(ee = 7))) expect_error(addOptPathEl(op, x = list(v = 1), y = 5, extra = list(ee = 7, ff = 1)), "Trying to add unknown extra\\(s\\): ff") expect_error(addOptPathEl(op, x = list(v = 1), y = 5, extra = list()), "You have to add extras to opt path if the option is enabled.") expect_error(addOptPathEl(op, x = list(v = 2), y = 6), "You have to add extras to opt path if the option is enabled.") }) test_that("exta entries with dots may be nonscalar", { ps = makeParamSet(makeNumericParam("v")) op = makeOptPathDF(par.set = ps, y.names = "y", minimize = TRUE, include.extra = TRUE) addOptPathEl(op, x = list(v = 1), y = 5, extra = list(ee = 7, .ee = list(1, list()))) df = setRowNames(as.data.frame(op), NULL) expect_equal(df, data.frame(v = 1, y = 5, dob = 1L, eol = NA_integer_, ee = 7)) expect_equal(getOptPathEl(op, 1L), list(x = list(v = 1), y = c(y = 5), dob = 1L, eol = NA_integer_, extra = list(ee = 7, .ee = list(1, list())))) # adding dotted extras with different names should be allowed addOptPathEl(op, x = list(v = 1), y = 5, extra = list(ee = 8, .ff = 1)) addOptPathEl(op, x = list(v = 1), y = 5, extra = list(ee = 9)) }) test_that("as.data.frame flags and getCols works", { ps = makeParamSet( makeNumericParam("x"), makeDiscreteParam("y", values = c("a", "b")) ) op = makeOptPathDF(par.set = ps, y.names = c("z1", "z2"), minimize = c(TRUE, TRUE), include.extra = TRUE) addOptPathEl(op, x = list(x = 1, y = "a"), y = c(z1 = 1, z2 = 4), extra = list(ee = 7, .ee = 8)) addOptPathEl(op, x = list(x = 2, y = "a"), y = c(z1 = 3, z2 = 2), extra = list(ee = 8, .ff = list(8, list()))) expect_error(as.data.frame(op, include.x = FALSE, include.y = FALSE, include.rest = FALSE), "include something") df1 = as.data.frame(op, include.rest = FALSE, discretes.as.factor = TRUE) df2 = as.data.frame(op, include.rest = FALSE, include.x = FALSE, discretes.as.factor = TRUE) df3 = as.data.frame(op, include.y = FALSE, include.x = FALSE, discretes.as.factor = TRUE) df4 = as.data.frame(op, include.y = TRUE, include.x = TRUE, include.rest = TRUE, dob = 2L) expect_equal(nrow(df1), 2) expect_equal(nrow(df2), 2) expect_equal(nrow(df3), 2) expect_equal(nrow(df4), 1) expect_equal(ncol(df2), 2) expect_equal(ncol(df3), 3) expect_equal(ncol(df4), 7) expect_equal(sapply(df1, class), c(x = "numeric", y = "factor", z1 = "numeric", z2 = "numeric")) expect_equal(sapply(df2, class), c(z1 = "numeric", z2 = "numeric")) expect_equal(sapply(df3, class), c(dob = "integer", eol = "integer", ee = "numeric")) # the dotted entries are not present as columns. expect_equal(sapply(df4, class), c(x = "numeric", y = "factor", z1 = "numeric", z2 = "numeric", dob = "integer", eol = "integer", ee = "numeric")) expect_error(getOptPathCol(op, "bla"), "not present") expect_equal(getOptPathCol(op, "dob"), c(1, 2)) expect_equal(getOptPathCol(op, "eol"), c(NA_integer_, NA_integer_)) expect_equal(getOptPathCol(op, "error.message"), NULL) expect_equal(getOptPathCol(op, "exec.time"), NULL) expect_equal(getOptPathCol(op, "x"), 1:2) expect_equal(getOptPathCol(op, "y"), c("a", "a")) expect_equal(getOptPathCol(op, "z1"), c(1, 3)) expect_equal(getOptPathCol(op, "ee"), c(7, 8)) expect_equal(getOptPathCol(op, ".ee"), list(8, NULL)) expect_equal(getOptPathCol(op, ".ff"), list(NULL, list(8, list()))) expect_equal(getOptPathCol(op, ".xx"), list(NULL, NULL)) d = getOptPathCols(op, c("x", "y")) expect_equal(dim(d), c(2L, 2L)) expect_equal(colnames(d), c("x", "y")) expect_true(is.factor(d$y)) d = getOptPathCols(op, "y") expect_equal(dim(d), c(2L, 1L)) expect_true(is.factor(d$y)) }) test_that("opt.path printing works", { ps = makeParamSet( makeNumericParam("x"), makeDiscreteParam("y", values = c("a", "b")) ) op = makeOptPathDF(par.set = ps, y.names = c("z1", "z2"), minimize = c(TRUE, FALSE)) expect_output(print(op), "Optimization path") addOptPathEl(op, x = list(x = 1, y = "a"), y = c(z1 = 1, z2 = 4)) expect_output(print(op), "Optimization path") op = makeOptPathDF(par.set = ps, y.names = "z1", minimize = TRUE, include.exec.time = TRUE) expect_output(print(op), "Exec times: TRUE. Range: 0 - 0. 0 NAs") addOptPathEl(op, x = list(x = 1, y = "a"), y = c(z1 = 1)) expect_output(print(op), "Exec times: TRUE. Range: 0 - 0. 1 NAs") addOptPathEl(op, x = list(x = 1, y = "a"), y = c(z1 = 1), exec.time = 3) expect_output(print(op), "Exec times: TRUE. Range: 3 - 3. 1 NAs.") op = makeOptPathDF(par.set = ps, y.names = c("z1", "z2"), minimize = c(TRUE, FALSE), include.extra = TRUE) expect_output(print(op), "Extras: NA columns") addOptPathEl(op, x = list(x = 1, y = "a"), y = c(z1 = 1, z2 = 4), extra = list(ee = 8, .ee = list(a = 1, b = 2))) expect_output(print(op), "Extras: 1 columns") }) ParamHelpers/tests/testthat/test_LearnerParam.R0000644000176000001440000001100313633666270021431 0ustar ripleyuserscontext("LearnerParam") test_that("num vec", { p = makeNumericVectorLearnerParam("x", len = 2, lower = 0, upper = 2) expect_equal(p$id, "x") expect_equal(p$lower, c(0, 0)) expect_equal(p$upper, c(2, 2)) expect_equal(p$when, "train") expect_true(!isFeasible(p, 1)) expect_true(isFeasible(p, c(1, 1))) p = makeNumericVectorLearnerParam("x", lower = 0, upper = 2, special.vals = list(NA_integer_)) expect_equal(p$lower, 0) expect_equal(p$upper, 2) expect_true(isFeasible(p, 1)) expect_true(isFeasible(p, c(1, 1))) expect_true(isFeasible(p, NA_integer_)) # defaults p = makeNumericVectorLearnerParam(id = "x", allow.inf = TRUE, default = Inf) expect_error(makeNumericVectorLearnerParam(id = "x", allow.inf = FALSE, default = Inf), "feasible") expect_error(makeNumericVectorLearnerParam(id = "x", allow.inf = FALSE, default = c(0, 0), lower = c(-1, -1)), "'lower' must be either 1 or length of param") expect_error(makeNumericVectorLearnerParam(id = "x", allow.inf = FALSE, default = c(0, 0), upper = c(1, 1)), "'upper' must be either 1 or length of param") }) test_that("int vec", { p = makeIntegerVectorLearnerParam("x", len = 2, lower = 0L, upper = 2L) expect_equal(p$id, "x") expect_equal(p$lower, c(0, 0)) expect_equal(p$upper, c(2, 2)) expect_equal(p$when, "train") expect_true(!isFeasible(p, 1)) expect_true(isFeasible(p, c(1, 1))) p = makeIntegerVectorLearnerParam("x", lower = 0L, upper = 2L) expect_equal(p$lower, 0) expect_equal(p$upper, 2) expect_true(isFeasible(p, 1)) expect_true(isFeasible(p, c(1, 1))) # defaults p = makeIntegerVectorLearnerParam(id = "x", len = NA_integer_, default = 1L) p = makeIntegerVectorLearnerParam(id = "x", len = NA_integer_, default = c(1L, 2L)) }) test_that("log vec", { p = makeLogicalVectorLearnerParam("x", len = 2) expect_equal(p$id, "x") expect_equal(p$values, list("TRUE" = TRUE, "FALSE" = FALSE)) expect_true(!isFeasible(p, TRUE)) expect_true(isFeasible(p, c(TRUE, FALSE))) p = makeLogicalVectorLearnerParam("x") expect_true(isFeasible(p, c(FALSE))) expect_true(isFeasible(p, c(TRUE, FALSE))) # defaults p = makeLogicalVectorLearnerParam(id = "x", len = NA_integer_, default = TRUE) p = makeLogicalVectorLearnerParam(id = "x", len = NA_integer_, default = c(TRUE, FALSE)) }) test_that("disc vec", { m = matrix(0, 2, 2) p = makeDiscreteVectorLearnerParam("x", len = 2, values = list(a = "a", b = m)) expect_equal(p$id, "x") expect_equal(p$values, list(a = "a", b = m)) expect_true(!isFeasible(p, "a")) expect_true(isFeasible(p, list("a", "a"))) expect_true(isFeasible(p, list(m, "a"))) p = makeDiscreteVectorLearnerParam("x", values = list(a = "a", b = m)) expect_true(isFeasible(p, list("a"))) expect_true(isFeasible(p, list(m))) expect_true(isFeasible(p, list("a", m, m))) # defaults p = makeDiscreteVectorLearnerParam(id = "x", len = NA_integer_, values = list("a", "b"), default = list("a")) p = makeDiscreteVectorLearnerParam(id = "x", len = NA_integer_, values = list("a", "b"), default = list("a", "b", "a")) }) test_that("untyped", { p = makeUntypedLearnerParam("x") expect_equal(p$id, "x") expect_true(isFeasible(p, 1)) expect_true(isFeasible(p, c())) expect_true(isFeasible(p, NULL)) p = makeUntypedLearnerParam("x", default = NULL) }) test_that("s4 objs works for values", { setClass("Dummy", representation(name = "character", id = "numeric")) obj.a = new("Dummy", name = "foo", id = 1) obj.b = new("Dummy", name = "bar", id = 2) vals = list(a = obj.a, b = obj.b) p = makeDiscreteLearnerParam("x", values = vals) expect_true(isFeasible(p, new("Dummy", name = "foo", id = 1))) expect_false(isFeasible(p, new("Dummy", name = "foo", id = 2))) p = makeDiscreteLearnerParam("x", values = vals, default = new("Dummy", name = "foo", id = 1)) expect_output(print(p), "a,b") }) test_that("unknown length works", { p = makeNumericVectorLearnerParam("x", len = NA, lower = 1) expect_true(isFeasible(p, c(2))) expect_true(isFeasible(p, c(2, 3))) expect_false(isFeasible(p, c(0))) expect_false(isFeasible(p, c(0, 0))) expect_error(sampleValue(p), "Cannot sample") }) test_that("expressions work", { ps = makeParamSet( makeNumericVectorLearnerParam("x"), makeNumericVectorLearnerParam("y", upper = expression(n)), keys = "n" ) expect_equal(getLower(ps), c(x = -Inf, y = -Inf)) expect_equal(getUpper(ps, dict = list(n = 100)), c(x = Inf, y = 100)) x = evaluateParamExpressions(ps, dict = list(n = 101)) expect_equal(x$pars$x$upper, Inf) expect_equal(x$pars$y$upper, 101) }) ParamHelpers/tests/testthat/test_generateGridDesign.R0000644000176000001440000001073713633666270022627 0ustar ripleyuserscontext("generateGridDesign") test_that("generateGridDesign", { ps = makeParamSet( makeNumericParam("x", lower = 1, upper = 5), makeIntegerParam("y", lower = 2, upper = 6) ) d = generateGridDesign(ps, resolution = 3L) e = expand.grid(x = c(1, 3, 5), y = c(2L, 4L, 6L), KEEP.OUT.ATTRS = FALSE) attr(e, "trafo") = FALSE expect_equal(d, e) ps = makeParamSet( makeNumericParam("u", lower = 1, upper = 5), makeIntegerParam("v", lower = 2, upper = 6), makeLogicalParam("w"), makeDiscreteParam("x", values = c("a", "b")) ) d = generateGridDesign(ps, resolution = 3L) e = expand.grid(u = c(1, 3, 5), v = c(2L, 4L, 6L), w = c(TRUE, FALSE), x = c("a", "b"), KEEP.OUT.ATTRS = FALSE) attr(e, "trafo") = FALSE expect_equal(d, e) # vectors ps = makeParamSet( makeNumericVectorParam("x", len = 2L, lower = 1, upper = 2), makeIntegerVectorParam("y", len = 2L, lower = 3, upper = 4), makeLogicalVectorParam("z", len = 2L) ) d = generateGridDesign(ps, resolution = 2L) e = expand.grid( x1 = c(1, 2), x2 = c(1, 2), y1 = c(3L, 4L), y2 = c(3L, 4L), z1 = c(TRUE, FALSE), z2 = c(TRUE, FALSE), KEEP.OUT.ATTRS = FALSE ) attr(e, "trafo") = FALSE expect_equal(d, e) # trafo ps = makeParamSet( makeNumericParam("x", lower = 0, upper = 1), makeNumericParam("y", lower = 3, upper = 4, trafo = function(x) 2 * x) ) d = generateGridDesign(ps, resolution = c(y = 4, x = 2), trafo = TRUE) e = expand.grid( x = seq(0, 1, length.out = 2), y = 2 * (seq(3, 4, length.out = 4)), KEEP.OUT.ATTRS = FALSE ) attr(e, "trafo") = TRUE expect_equal(d, e) ps = makeParamSet( makeNumericVectorParam("x", len = 2, lower = 1, upper = 2, trafo = function(x) x / sum(x)) ) d = generateGridDesign(ps, resolution = 4, trafo = TRUE) e = expand.grid( x1 = seq(1, 2, length.out = 4), x2 = seq(1, 2, length.out = 4), KEEP.OUT.ATTRS = FALSE ) f = as.data.frame(t(apply(e, 1, function(x) x / sum(x)))) f = f[!duplicated(f), ] attr(f, "trafo") = TRUE expect_equal(setRowNames(d, NULL), setRowNames(f, NULL)) }) test_that("requires works", { ps = makeParamSet( makeDiscreteParam("x", values = c("a", "b")), makeNumericParam("y", lower = 1, upper = 2, requires = quote(x == "a")) ) des = generateGridDesign(par.set = ps, resolution = 3) vals = dfRowsToList(des, ps) oks = sapply(vals, isFeasible, par = ps) expect_true(all(oks)) ps = makeParamSet( makeDiscreteParam("x", values = c("a", "b")), makeNumericVectorParam("y", len = 2, lower = 1, upper = 2, requires = quote(x == "a")) ) des = generateGridDesign(par.set = ps, resolution = 3) vals = dfRowsToList(des, ps) oks = sapply(vals, isFeasible, par = ps) expect_true(all(oks)) }) test_that("nested requires", { ps7 = makeParamSet( makeDiscreteParam("disc", values = c("a", "b", "c")), makeNumericParam("realA", lower = 0, upper = 100, requires = quote(disc == "a")), makeIntegerParam("intA", lower = -100, upper = 100, requires = quote(disc == "a")), makeDiscreteParam("discA", values = c("m", "w"), requires = quote(disc == "a")), makeNumericParam("realB", lower = -100, upper = 100, requires = quote(disc == "b")), makeDiscreteParam("discB", values = c("R", "NR"), requires = quote(disc == "b")), makeNumericParam("realBR", lower = 0, upper = 2 * pi, requires = quote(identical(discB, "R") && identical(disc, "b"))), makeNumericParam("realBNR", lower = 0, upper = 2 * pi, requires = quote(identical(discB, "NR") && identical(disc, "b"))) ) des = generateGridDesign(par.set = ps7, resolution = 3) expect_true(all(is.na(des[des$disc == "a", 5:8]))) expect_true(all(is.na(des[des$disc == "b", 2:4]))) expect_true(all(is.na(des[des$disc == "c", 2:8]))) expect_true(all(is.na(des[des$disc == "b" & des$discB == "NR", 7]))) expect_true(all(is.na(des[des$disc == "b" & des$discB == "R", 8]))) vals = dfRowsToList(des, ps7) oks = sapply(vals, isFeasible, par = ps7) expect_true(all(oks)) }) test_that("discrete works without resolution", { ps8 = makeParamSet( makeDiscreteParam("disc", values = c("c", "b", "a")), makeDiscreteParam("discA", values = c("m", "w"), requires = quote(disc == "a")), makeLogicalParam("logA") ) des = generateGridDesign(par.set = ps8) expect_true(nrow(des) == 8) expect_true(all(is.na(des[des$disc == "c", "discA"]))) expect_true(all(is.na(des[des$disc == "b", "discA"]))) expect_equal(levels(des[, 2]), c("m", "w")) expect_equal(levels(des[, 1]), c("c", "b", "a")) }) ParamHelpers/tests/testthat/test_sample.R0000644000176000001440000001075413633666270020355 0ustar ripleyuserscontext("sample") test_that("numeric sampling", { p = makeNumericParam(id = "x", lower = 10, upper = 20) r = sampleValues(p, 13) expect_true(is.list(r)) r = unlist(r) expect_true(is.numeric(r)) expect_equal(length(r), 13) expect_true(all(!is.na(r))) expect_true(all(r >= p$lower & r <= p$upper)) }) test_that("numeric vector sampling", { p = makeNumericVectorParam(id = "x", len = 2, lower = 10, upper = 20) r = sampleValues(p, 1000) r = do.call(rbind, r) expect_true(all(r >= p$lower & r <= p$upper)) }) test_that("integer sampling", { p = makeIntegerParam(id = "x", lower = 10, upper = 20) r = sampleValues(p, 13) expect_true(is.list(r)) r = unlist(r) expect_true(is.integer(r)) expect_equal(length(r), 13) expect_true(all(!is.na(r))) expect_true(all(r >= p$lower & r <= p$upper)) }) test_that("integer vector sampling", { p = makeIntegerVectorParam(id = "x", len = 2, lower = 1, upper = 3) r = sampleValues(p, 1000) r = do.call(rbind, r) expect_true(all(r >= p$lower & r <= p$upper)) # this is stochastic, we dont want that on CRAN as it can fail if (interactive()) { r = as.numeric(table(r)) expect_true(all(r > 600 & r < 730)) } }) test_that("logical sampling", { p = makeLogicalParam(id = "x") r = sampleValues(p, 13) expect_true(is.list(r)) r = unlist(r) expect_true(is.logical(r)) expect_equal(length(r), 13) expect_true(all(!is.na(r))) }) test_that("logical vector sampling", { p = makeLogicalVectorParam(id = "x", len = 2) r = sampleValues(p, 1000) expect_true(is.list(r)) expect_true(all(sapply(r, function(x) is.logical(x) && length(x) == 2))) expect_true(setequal(unique(unlist(r)), c(TRUE, FALSE))) r = do.call(rbind, r) if (interactive()) { r1 = as.numeric(table(r[, 1])) expect_true(all(r1 > 300)) r2 = as.numeric(table(r[, 2])) expect_true(all(r2 > 300)) } }) test_that("discrete sampling", { p = makeDiscreteParam(id = "x", values = c("a", "b", "c")) r = sampleValues(p, 13) expect_true(is.list(r)) r = unlist(r) expect_true(is.character(r)) expect_equal(length(r), 13) expect_true(all(!is.na(r))) expect_true(all(r %in% p$values)) p = makeDiscreteParam(id = "x", values = c(xx = "a", yy = "b")) r = sampleValues(p, 13, discrete.names = TRUE) expect_true(is.list(r)) r = unlist(r) expect_true(is.character(r)) expect_equal(length(r), 13) expect_true(all(!is.na(r))) expect_true(all(r %in% c("xx", "yy"))) p = makeDiscreteParam(id = "x", values = list(a = list(), b = 1:3)) r = sampleValues(p, 10) expect_true(is.list(r)) expect_equal(length(r), 10) expect_true(all(r %in% p$values)) p = makeDiscreteVectorParam(id = "x", len = 2, values = list(a = list(), b = 1:3)) r = sampleValues(p, 10) expect_true(is.list(r)) expect_equal(length(r), 10) ok = function(x) { is.list(x) && length(x) == 2 && (length(x[[1]]) == 0L || all(x[[1]] %in% 1:3)) && (length(x[[2]]) == 0L || all(x[[2]] %in% 1:3)) } expect_true(all(sapply(r, ok))) }) test_that("bounds checked", { expect_error(sampleValue(makeNumericParam("u", lower = 2)), "Cannot sample") expect_error(sampleValue(makeNumericParam("u", upper = 2)), "Cannot sample") expect_error(sampleValue(makeIntegerVectorParam("u", len = 2, lower = 2)), "Cannot sample") expect_error(sampleValue(makeIntegerVectorParam("u", len = 2, upper = 2)), "Cannot sample") }) test_that("sampleValues with paramset works", { ps = makeParamSet( makeIntegerParam("x", lower = 20, upper = 100), makeDiscreteParam("y", values = c(xx = "a", yy = "b")) ) r = sampleValues(ps, 5, discrete.names = TRUE) expect_true(is.list(r)) expect_equal(length(r), 5) expect_true(all(sapply(r, function(x) is.numeric(x[[1]]) && x[[1]] >= 1 && x[[1]] <= 100))) expect_true(all(sapply(r, function(x) x[[2]] %in% c("xx", "yy")))) }) test_that("requires works", { ps = makeParamSet( makeDiscreteParam("x", values = c("a", "b")), makeNumericParam("y", lower = 1, upper = 2, requires = quote(x == "a")), makeIntegerVectorParam("z", len = 2, lower = 1, upper = 20, requires = quote(x == "b")), makeDiscreteParam("w", values = 1:2, requires = quote(x == "a")) ) vals = sampleValues(ps, n = 100) oks = sapply(vals, function(v) isFeasible(ps, v)) expect_true(all(oks)) }) test_that("trafo works", { ps = makeParamSet( makeNumericParam("x", lower = -2, upper = 2, trafo = function(x) 2^x) ) vals = sampleValues(ps, n = 100, trafo = TRUE) vals = extractSubList(vals, "x") expect_true(all(vals >= 2^(-2) & vals <= 2^2)) }) ParamHelpers/tests/testthat/test_isSpecialValue.R0000644000176000001440000000074413633666270022003 0ustar ripleyuserscontext("isSpecialValue") test_that("isSpecialValue", { p = makeIntegerParam("a", special.vals = list(NULL)) expect_true(isSpecialValue(p, NULL)) expect_false(isSpecialValue(p, 1)) expect_false(isSpecialValue(p, 1.5)) expect_false(isSpecialValue(p, iris)) p = makeIntegerParam("a", special.vals = list(iris, 1.5)) expect_false(isSpecialValue(p, NULL)) expect_false(isSpecialValue(p, 1)) expect_true(isSpecialValue(p, 1.5)) expect_true(isSpecialValue(p, iris)) }) ParamHelpers/tests/testthat/test_isVector.R0000644000176000001440000000124113633666270020661 0ustar ripleyuserscontext("isVector") test_that("isVector", { ps = makeParamSet() expect_true(isVector(ps)) non.vector.ps = makeParamSet( makeDiscreteParam("disc", values = letters[1:3]), makeLogicalVectorParam("logi", len = 2L) ) expect_false(isVector(non.vector.ps)) expect_false(isVector(non.vector.ps$pars[[1L]])) expect_true(isVector(non.vector.ps$pars[[2L]])) vector.ps = makeParamSet( makeNumericVectorParam("num", len = 2L, lower = 0, upper = 5), makeDiscreteVectorParam("disc", len = 4L, values = letters[1:3]) ) expect_true(isVector(vector.ps)) expect_true(isVector(vector.ps$pars[[1L]])) expect_true(isVector(vector.ps$pars[[2L]])) }) ParamHelpers/tests/testthat/test_getParamTypes.R0000644000176000001440000000223113164130622021632 0ustar ripleyuserscontext("getParamTypes") test_that("getParamTypes", { ps = makeParamSet( makeDiscreteParam("x", values = c("a", "b")), makeNumericVectorParam("y", len = 2), makeIntegerParam("z"), makeCharacterVectorParam("s", len = 2) ) expect_equal( getParamTypes(ps, df.cols = FALSE, use.names = FALSE), c("discrete", "numericvector", "integer", "charactervector") ) expect_equal( getParamTypes(ps, df.cols = TRUE, use.names = FALSE), c("factor", "numeric", "numeric", "integer", "character", "character") ) expect_equal( getParamTypes(ps, df.cols = FALSE, use.names = TRUE), c(x = "discrete", y = "numericvector", z = "integer", s = "charactervector") ) expect_equal( getParamTypes(ps, df.cols = TRUE, use.names = TRUE, with.nr = FALSE), c(x = "factor", y = "numeric", y = "numeric", z = "integer", s = "character", s = "character") ) expect_equal( getParamTypes(ps, df.cols = TRUE, use.names = TRUE, with.nr = TRUE), c(x = "factor", y1 = "numeric", y2 = "numeric", z = "integer", s1 = "character", s2 = "character") ) expect_equal( getParamTypes(makeParamSet()), character(0L) ) }) ParamHelpers/tests/testthat/test_getDefaults.R0000644000176000001440000000474413633666270021345 0ustar ripleyuserscontext("getDefaults") test_that("getDefaults", { ps = makeParamSet() expect_equal(getDefaults(ps), list()) ps = makeParamSet( makeNumericParam("u", default = 2), makeIntegerParam("v"), makeCharacterParam("s", default = "foo"), makeUntypedParam("w", default = iris) ) expect_equal(getDefaults(ps), list(u = 2, s = "foo", w = iris)) ps = makeParamSet( makeIntegerParam("v") ) expect_equal(getDefaults(ps), list()) # test include.null ps = makeParamSet( makeDiscreteParam("x", values = c("a", "b"), default = "a"), makeNumericVectorParam("y", len = 2), makeIntegerParam("z", default = 99) ) expect_equal( getDefaults(ps, include.null = TRUE), list(x = "a", y = NULL, z = 99) ) expect_equal( getDefaults(ps, include.null = FALSE), list(x = "a", z = 99) ) }) test_that("getDefaults for LearnerParams", { par.set = makeParamSet( makeDiscreteLearnerParam(id = "a", default = "a1", values = c("a1", "a2")), makeNumericLearnerParam(id = "b", default = 1, lower = 0, requires = quote(a == "a1")), makeNumericVectorLearnerParam("c", len = NA_integer_, lower = 0), makeLogicalVectorLearnerParam(id = "d", default = c(TRUE), tunable = TRUE), makeIntegerVectorLearnerParam(id = "e", default = 1:3) ) expect_equal( getDefaults(par.set, include.null = TRUE), list(a = "a1", b = 1, c = NULL, d = TRUE, e = 1:3) ) }) test_that("getDefaults for Parameters with Expressions", { par.set = makeParamSet( makeNumericLearnerParam(id = "b", default = expression(k), lower = 0, requires = quote(a == "a1")), makeNumericVectorLearnerParam("c", len = NA_integer_, lower = 0), makeLogicalVectorLearnerParam(id = "d", len = expression(p), default = TRUE, tunable = TRUE) ) expect_equal( getDefaults(par.set, dict = list(k = 4L, p = 3L)), list(b = 4L, d = rep(TRUE, 3L)) ) expect_equal( getDefaults(par.set, dict = list(k = 4L, p = 3L), include.null = TRUE), list(b = 4, c = NULL, d = rep(TRUE, 3L)) ) expect_equal(getDefaults(makeNumericParam(id = "b", default = expression(k)), dict = list(k = 4L)), 4L) par.vals = list( makeNumericLearnerParam(id = "b", default = expression(k), requires = quote(a == "a1")), makeNumericVectorLearnerParam("c", len = NA_integer_, lower = 0), makeLogicalVectorLearnerParam(id = "d", len = expression(p), default = TRUE, tunable = TRUE) ) expect_equal( getDefaults(par.vals, dict = list(k = pi, p = 7L)), list(pi, rep(TRUE, 7L)) ) }) ParamHelpers/tests/testthat/test_plotEAF.R0000644000176000001440000000170713633666270020364 0ustar ripleyuserscontext("plotEAF") test_that("plotEAF works", { # Build 3 artifical opt.paths with 2 crits makeArtOP = function() { ps = makeNumericParamSet(len = 1L) op = makeOptPathDF(par.set = ps, y.names = c("y1", "y2"), minimize = c(TRUE, TRUE)) X = rnorm(60) dob = c(rep(0, 5), 1:15) for (i in 1:20) { addOptPathEl(op, x = list( x = X[i * 3]), y = X[ i * 3 - 1:2], dob = dob[i]) } op } # build aritificial list of opt pathes opt.paths = list( algo1 = list(makeArtOP(), makeArtOP(), makeArtOP()), algo2 = list(makeArtOP(), makeArtOP()), algo3 = list(makeArtOP())) # plot eaf and check returned data frame res = plotEAF(opt.paths) algo.names = c("algo1", "algo2", "algo3") expect_true(is.data.frame(res)) expect_true(setequal(colnames(res), c("y1", "y2", ".algo", ".repl"))) expect_true(all(res$.algo %in% algo.names)) expect_true(all(res$.repl >= 1) && all(res$.repl <= 3)) }) ParamHelpers/tests/testthat/test_hasExpression.R0000644000176000001440000000261713164130622021710 0ustar ripleyuserscontext("hasExpression") test_that("hasExpression.Param", { expect_true(!hasExpression(obj = makeDiscreteParam("u", values = 1:2))) expect_true(hasExpression(obj = makeDiscreteParam("v", values = expression(n * p)))) expect_true(!hasExpression(obj = makeNumericParam("w", lower = -Inf))) expect_true(hasExpression(obj = makeNumericParam("x", lower = expression(ceiling(n))))) }) test_that("hasExpression.ParamSet", { ps1 = makeParamSet( makeNumericParam("x", lower = 1, upper = 2), makeNumericParam("y", lower = 1, upper = 10) ) ps2 = makeParamSet( makeNumericLearnerParam("x", lower = 1, upper = 2), makeNumericLearnerParam("y", lower = 1, upper = expression(p)) ) ## providing the correct key is ok ps3 = makeParamSet( makeNumericParam("x", lower = 1, upper = 2), makeNumericParam("y", lower = 1, upper = expression(a)), keys = "a" ) # providing the wrong key will result in an error expect_error(makeParamSet( makeNumericParam("x", lower = 1, upper = 2), makeNumericParam("y", lower = 1, upper = expression(a)), keys = "b" )) expect_true(!hasExpression(ps1)) expect_true(hasExpression(ps2)) expect_true(hasExpression(ps3)) }) test_that("hasExpression.list", { par.vals = list( makeLogicalParam("x", default = expression(a == 3)), makeNumericParam("y", lower = 1, upper = expression(a)) ) expect_true(hasExpression(par.vals)) }) ParamHelpers/tests/testthat/test_generateRandomDesign.R0000644000176000001440000000414713633666270023160 0ustar ripleyuserscontext("generateRandomDesign") test_that("num/int/disc vec design", { ps = makeParamSet( makeNumericParam("x", lower = -2, upper = 1), makeIntegerVectorParam("y", len = 3, lower = 10L, upper = 20L), makeDiscreteVectorParam("z", len = 2, values = list(a = "a", b = list())), makeLogicalVectorParam("a", len = 2) ) des = generateRandomDesign(13, ps) expect_equal(nrow(des), 13) expect_equal(ncol(des), 8) expect_equal(colnames(des), c("x", "y1", "y2", "y3", "z1", "z2", "a1", "a2")) expect_true(is.numeric(des[, 1])) expect_true(is.integer(des[, 2])) expect_true(is.integer(des[, 3])) expect_true(is.integer(des[, 4])) expect_true(is.factor(des[, 5])) expect_true(is.factor(des[, 6])) expect_true(is.logical(des[, 7])) expect_true(is.logical(des[, 8])) expect_true(all(des[, 1] >= -2) && all(des[, 1] <= 1)) expect_true(all(des[, 2] >= 10) && all(des[, 2] <= 20)) expect_true(all(des[, 3] >= 10) && all(des[, 3] <= 20)) expect_true(all(des[, 4] >= 10) && all(des[, 4] <= 20)) expect_true(all(des[, 5] %in% c("a", "b"))) expect_true(all(des[, 6] %in% c("a", "b"))) expect_equal(levels(des[, 5]), c("a", "b")) expect_equal(levels(des[, 6]), c("a", "b")) }) test_that("requires works", { ps = makeParamSet( makeDiscreteParam("x", values = c("a", "b")), makeNumericParam("y", lower = 1, upper = 2, requires = quote(x == "a")), makeDiscreteParam("z", values = 1:2, requires = quote(x == "b")) ) des = generateRandomDesign(50, par.set = ps) vals = dfRowsToList(des, ps) oks = sapply(vals, isFeasible, par = ps) expect_true(all(oks)) ps = makeParamSet( makeDiscreteParam("x", values = c("a", "b")), makeNumericVectorParam("y", len = 2, lower = 1, upper = 2, requires = quote(x == "a")) ) des = generateDesign(50, par.set = ps) vals = dfRowsToList(des, ps) oks = sapply(vals, isFeasible, par = ps) expect_true(all(oks)) }) test_that("we dont drop levels in factors", { ps = makeParamSet( makeDiscreteParam("x", values = letters[5:1]) ) des = generateRandomDesign(1, ps) expect_true(is.factor(des$x) && all(levels(des$x) == letters[5:1])) }) ParamHelpers/tests/testthat/test_evaluateParamExpressions.R0000644000176000001440000000326513164130622024107 0ustar ripleyuserscontext("evaluateParamExpressions") test_that("no changes", { ps = makeParamSet() expect_identical(evaluateParamExpressions(ps), ps) expect_identical(evaluateParamExpressions(ps, dict = list(p = 3)), ps) ps = makeParamSet( makeNumericParam("u", lower = 3), makeIntegerParam("v", lower = 1, upper = 9), makeDiscreteParam("w", default = "b", values = c("a", "b")), makeDiscreteParam("x", default = "a", values = c("a", "b")) ) expect_identical(evaluateParamExpressions(ps, dict = list(p = 3, z = "b")), ps) expect_identical(evaluateParamExpressions(ps), ps) expect_identical(evaluateParamExpressions(ps, dict = list(p = 3)), ps) expect_identical(evaluateParamExpressions(ps, dict = list(z = "b")), ps) }) test_that("expressions", { ps = makeParamSet( makeNumericParam("u", lower = expression(p)), makeIntegerParam("v", lower = 1, upper = expression(3 * p)), makeDiscreteParam("w", default = expression(z), values = c("a", "b")), makeDiscreteParam("x", default = "a", values = c("a", "b")), keys = c("p", "z") ) ps2 = makeParamSet( makeNumericParam("u", lower = 3), makeIntegerParam("v", lower = 1, upper = 9), makeDiscreteParam("w", default = "b", values = c("a", "b")), makeDiscreteParam("x", default = "a", values = c("a", "b")) ) dict = list(p = 3, z = "b") expect_identical(evaluateParamExpressions(ps, dict = dict), ps2) expect_error(evaluateParamExpressions(ps)) expect_error(evaluateParamExpressions(ps, dict = list(p = 3))) expect_error(evaluateParamExpressions(ps, dict = list(z = "b"))) pv = list(x = expression(k), y = 5) expect_identical(evaluateParamExpressions(pv, dict = list(k = 3)), list(x = 3, y = 5)) }) ParamHelpers/tests/testthat/test_dfRowToList.R0000644000176000001440000000445613633666270021316 0ustar ripleyuserscontext("dfRowToList") test_that("dfRowToList", { ps = makeParamSet( makeDiscreteParam("x", values = list(a = iris, b = 123)), makeNumericParam("y", lower = 1, upper = 2), makeNumericVectorParam("z", len = 2, lower = 10, upper = 20) ) des = generateDesign(10, par.set = ps) vals = dfRowsToList(des, ps) expect_true(is.list(vals) && length(vals) == nrow(des)) for (i in seq_row(des)) { v = vals[[i]] expect_true(is.list(v) && length(v) == 3 && all(names(v) == c("x", "y", "z"))) expect_true(identical(v$x, iris) || identical(v$x, 123)) expect_true(is.numeric(v$y) && length(v$y) == 1 && v$y >= 1 && v$y <= 2) expect_true(is.numeric(v$z) && length(v$z) == 2 && all(v$z >= 10 & v$z <= 20)) } }) test_that("requires works", { ps = makeParamSet( makeDiscreteParam("x", values = c("a", "b")), makeNumericParam("y", lower = 1, upper = 2, requires = quote(x == "a")), makeNumericVectorParam("z", len = 2, lower = 10, upper = 20, requires = quote(x == "b")) ) des = generateDesign(10, par.set = ps) mycheck = function(vals) { expect_true(is.list(vals) && length(vals) == nrow(des)) for (i in seq_row(des)) { v = vals[[i]] expect_true(is.list(v) && length(v) == 3L && all(names(v) %in% c("x", "y", "z"))) expect_true(is.character(v$x) && length(v$x) == 1 && v$x %in% c("a", "b")) if (v$x == "a") { expect_true(is.numeric(v$y) && length(v$y) == 1 && v$y >= 1 && v$y <= 2) expect_true(isScalarNA(v$z)) } else if (v$x == "b") { expect_true(isScalarNA(v$y)) expect_true(is.numeric(v$z) && length(v$z) == 2 && all(v$z >= 10 & v$z <= 20)) } } } vals = dfRowsToList(des, ps) mycheck(vals) }) test_that("ints in data frame work", { df = data.frame(x = 1:3, y = as.numeric(1:3)) ps = makeParamSet( makeIntegerParam("x"), makeIntegerParam("y") ) xs = dfRowsToList(df, ps) expect_equal(xs[[1]], list(x = 1L, y = 1L)) }) test_that("enforce.col.types works", { df = data.frame(u = c(NA, NA), x = 1:2, y = as.numeric(1:2), z = c("TRUE", "FALSE")) ps = makeParamSet( makeNumericParam("u"), makeIntegerParam("x"), makeIntegerParam("y"), makeLogicalParam("z") ) x = dfRowToList(df, ps, 1L, enforce.col.types = TRUE) expect_equal(x, list(u = NA, x = 1L, y = 1L, z = TRUE)) }) ParamHelpers/tests/testthat/test_getRequiredParamNames.R0000644000176000001440000000117613164130622023301 0ustar ripleyuserscontext("getRequiredParamNames") test_that("getRequiredParamNames", { ps = makeParamSet( makeIntegerParam("a", default = 1L), makeIntegerParam("b", default = 1L, requires = quote(a == 1)), makeIntegerParam("c", default = 1L, requires = quote(a == 2 && b == 1)) ) expect_equal(getRequiredParamNames(ps), c("a", "b")) ps2 = filterParams(ps, ids = c("b", "c")) expect_equal(getRequiredParamNames(ps2), c("a", "b")) ps2 = filterParams(ps, ids = c("c")) expect_equal(getRequiredParamNames(ps2), c("a", "b")) ps2 = filterParams(ps, ids = character(0)) expect_equal(getRequiredParamNames(ps2), character(0)) }) ParamHelpers/tests/testthat/test_hasIsType.R0000644000176000001440000000433213164130622020762 0ustar ripleyuserscontext("is{Discrete, Integer, Numeric, Character} and has{Discrete, Integer, Numeric, Character}") test_that("is{Discrete, Integer, Numeric, Character} and has{Discrete, Integer, Numeric, Character}", { par.set.empty = makeParamSet() has.methods = c(hasInteger, hasDiscrete, hasNumeric, hasCharacter) is.methods = c(isInteger, isDiscrete, isNumeric, isCharacter) lapply(has.methods, function(fun) expect_false(fun(par.set.empty))) lapply(is.methods, function(fun) expect_true(fun(par.set.empty))) par.set.mixed = makeParamSet( makeNumericParam("u", lower = 1), makeIntegerParam("v", lower = 1, upper = 2), makeDiscreteParam("w", values = 1:2), makeLogicalParam("x"), makeDiscreteVectorParam("y", len = 2, values = c("a", "b")) ) par.set.discrete = makeParamSet( makeDiscreteParam("discr1", values = 1:2), makeDiscreteParam("discr2", values = letters[1:3]), makeDiscreteVectorParam("y", len = 2, values = c("x", "y")) ) par.set.character = makeParamSet( makeCharacterParam("char1"), makeCharacterVectorParam("chars1", len = 2L) ) par.set.logical = makeParamSet( makeLogicalParam("logi1"), makeLogicalVectorParam("logi2", len = 3L) ) expect_true(isDiscrete(par.set.discrete)) expect_true(hasDiscrete(par.set.discrete)) expect_false(isInteger(par.set.discrete)) expect_false(isNumeric(par.set.discrete)) expect_false(hasNumeric(par.set.discrete)) expect_false(hasInteger(par.set.discrete)) expect_true(isCharacter(par.set.character)) expect_false(hasInteger(par.set.character)) expect_false(isDiscrete(par.set.mixed)) expect_false(isInteger(par.set.mixed)) expect_false(isNumeric(par.set.mixed)) expect_false(isCharacter(par.set.mixed)) expect_true(hasNumeric(par.set.mixed)) expect_true(hasInteger(par.set.mixed)) expect_false(hasCharacter(par.set.mixed)) expect_true(hasLogical(par.set.mixed)) expect_true(isDiscrete(par.set.logical)) expect_false(isDiscrete(par.set.logical, include.logical = FALSE)) expect_true(hasDiscrete(par.set.logical)) expect_false(hasDiscrete(par.set.logical, include.logical = FALSE)) expect_false(isNumeric(par.set.logical)) expect_true(hasLogical(par.set.logical)) expect_true(isLogical(par.set.logical)) }) ParamHelpers/tests/testthat/test_cnames.R0000644000176000001440000000234013633666270020332 0ustar ripleyuserscontext("cnames") test_that("cnames work with different operations", { p = makeNumericVectorParam(id = "x", len = 2L, lower = 0, upper = 1, cnames = c("a", "b")) x = sampleValue(p) expect_equal(names(x), c("a", "b")) xs = sampleValues(p, 2L) lapply(xs, function(x) expect_equal(names(x), c("a", "b"))) expect_true(isFeasible(p, x)) expect_false(isFeasible(p, c(0.1, 0.1))) ps = makeParamSet(p) des = generateDesign(2, ps) xs = dfRowsToList(des, ps) lapply(xs, function(x) expect_equal(names(x$x), c("a", "b"))) p = makeIntegerVectorParam(id = "x", len = 2L, lower = 0, upper = 10, cnames = c("a", "b")) x = setValueCNames(p, c(1L, 1L)) expect_equal(x, c(a = 1L, b = 1L)) p = makeIntegerParam(id = "x") x = setValueCNames(p, 1L) expect_equal(x, 1L) }) test_that("cnames work with dep params", { ps = makeParamSet( makeDiscreteParam("x", values = c("a", "b")), makeNumericVectorParam("y", lower = 1, upper = 2, len = 2L, requires = quote(x == "a"), cnames = c("xxx", "yyy")) ) x = setValueCNames(ps, list(x = "a", y = c(1, 2))) expect_equal(x, list(x = "a", y = c(xxx = 1, yyy = 2))) x = setValueCNames(ps, list(x = "b", y = NA_real_)) expect_equal(x, list(x = "b", y = NA_real_)) }) ParamHelpers/tests/testthat/test_renderOptPathPlot.R0000644000176000001440000001001413633666270022477 0ustar ripleyuserscontext("renderOptPathPlot") muffle = function(x) expect_warning(x, "to numeric for over time plot") test_that("renderOptPathPlot", { # Test 1D-1D + short names + alpha + title ps0 = makeParamSet( makeNumericParam("x") ) op0 = makeOptPathDF(par.set = ps0, y.names = c("y"), minimize = TRUE) X = rnorm(14) dob = c(rep(0, 5), 1:2) for (i in 1:7) { addOptPathEl(op0, x = list( x = X[i * 2]), y = X[ i * 2 - 1], dob = dob[i]) } pl = renderOptPathPlot(op0, iter = 0, alpha = FALSE) pl = sapply(c(0, 2), FUN = function(x) { renderOptPathPlot(op0, iter = x, short.x.names = "e", short.y.names = "f") }) pl = plotOptPath(op0, iters = 0:2, pause = FALSE, title = "Optimization Path") # Test 2D(mixed)-3D + marked + ggplot.theme + log + size ps1 = makeParamSet( makeNumericParam("x"), makeDiscreteParam("z", values = list("a", "b")) ) op1 = makeOptPathDF(par.set = ps1, y.names = c("y1", "y2", "y3"), minimize = c(TRUE, FALSE, TRUE)) X = rnorm(100) Z = rnorm(25) Z = ifelse(Z < 0, "a", "b") dob = c(rep(0, 5), 1:20) for (i in 1:25) { addOptPathEl(op1, x = list(x = abs(X[i * 4 - 3]), z = Z[i]), y = c(y1 = X[i * 4 - 2], y2 = abs(X[i * 4 - 1]), y3 = abs(X[i * 4])), dob = dob[i]) } muffle({ pl = renderOptPathPlot(op1, iter = 3) }) pl = sapply(c(0, 20), FUN = function(x) { muffle(renderOptPathPlot(op1, iter = x, marked = "best", ggplot.theme = ggplot2::theme(legend.position = "bottom"), size.points = 1, size.lines = 3)) }) pl = sapply(c(0, 20), FUN = function(x) { muffle(renderOptPathPlot(op1, iter = x, marked = c(4, 10, 18), x.over.time = list(c("x"), c("z")), y.over.time = list(c("y1"), c("y2", "y3")), log = c("x", "y2", "y3"))) }) # Test 1D(discrete)-2D + marked + limits + short names + rest variables ps2 = makeParamSet( makeDiscreteParam("x", values = list("a", "b")) ) op2 = makeOptPathDF(par.set = ps2, y.names = c("y1", "y2"), minimize = c(TRUE, TRUE), include.extra = TRUE) X = rep(c("a", "b"), 4) Y = rnorm(14) dob = c(rep(0, 5), 1:2) for (i in 1:5) { addOptPathEl(op2, x = list(x = X[i]), y = c(y1 = Y[i], y2 = Y[7 + i]), dob = dob[i], extra = list(extra.var = NA)) } for (i in 6:7) { addOptPathEl(op2, x = list(x = X[i]), y = c(y1 = Y[i], y2 = Y[7 + i]), dob = dob[i], extra = list(extra.var = i)) } muffle({ pl = renderOptPathPlot(op2, iter = 2, x.over.time = list(c("x"), c("extra.var")), short.rest.names = c("extra")) }) pl = sapply(c(0, 2), FUN = function(x) { muffle(renderOptPathPlot(op2, iter = x, marked = c(3), xlim = list(YSpace = c(-10, 10)), ylim = list(YSpace = c(-10, 10), XSpace = c(0, 10)), short.x.names = "variable1", short.y.names = c("y", "z"))) }) # Test 3D(mixed)-1D + colours + missing values + limits + short names + scale + # impute.scale + impute.value ps3 = makeParamSet( makeNumericParam("x"), makeNumericParam("y", requires = quote(x < 0.7)), makeDiscreteParam("z", values = list("a", "b", "c"), requires = quote(x > -0.7)) ) op3 = makeOptPathDF(par.set = ps3, y.names = c("y1"), minimize = c(TRUE)) X = rnorm(7) X2 = rnorm(7) Y = rnorm(7) X2[X >= 0.7] = NA X3 = rep(c("a", "b", "c"), 5) X3[X <= -0.7] = NA dob = c(rep(0, 5), 1:2) for (i in 1:7) { addOptPathEl(op3, x = list(x = X[i], y = X2[i], z = X3[i]), y = c(y1 = Y[i]), dob = dob[i]) } pl = sapply(c(0, 2), FUN = function(x) { muffle(renderOptPathPlot(op3, iter = x, scale = "globalminmax", impute.scale = 2, impute.value = "miss")) }) pl = sapply(c(0, 2), FUN = function(x) { muffle(renderOptPathPlot(op3, iter = x, xlim = list(YSpace = c(-0.5, 0.5)), short.x.names = c("a", "b", "c"), colours = c("black", "yellow", "orange", "green"), scale = "globalminmax")) }) # Test subsetting muffle(renderOptPathPlot(op1, iter = 2, subset.obs = c(1, 2, 6, 7))) renderOptPathPlot(op1, iter = 0, subset.vars = 1) muffle(renderOptPathPlot(op1, iter = 0, subset.targets = 2:3)) }) ParamHelpers/tests/testthat/test_repairPoint.R0000644000176000001440000000116013633666270021357 0ustar ripleyuserscontext("repairPoint") test_that("repairPoint", { ps = makeParamSet( makeNumericParam("num1", lower = 1, upper = 5), makeIntegerParam("num2", lower = 1, upper = 10), makeNumericVectorParam("num3", len = 2L, lower = 1, upper = 5), makeDiscreteParam("disc1", values = letters[1:10]) ) # sample values violating bounds for numeric params x = list(num1 = -2, num2 = 11, num3 = c(2, 10), disc1 = "b") x.repaired = repairPoint(ps, x) expect_true(x.repaired$num1 == 1) expect_true(x.repaired$num2 == 10) expect_true(all(x.repaired$num3 == c(2, 5))) expect_true(x.repaired$disc1 == x$disc1) }) ParamHelpers/tests/testthat/Rplots.pdf0000644000176000001440000003360713636350123017660 0ustar ripleyusers%PDF-1.4 %âãÏÓ\r 1 0 obj << /CreationDate (D:20200324101807) /ModDate (D:20200324101807) /Title (R Graphics Output) /Producer (R 3.6.3) /Creator (R) >> endobj 2 0 obj << /Type /Catalog /Pages 3 0 R >> endobj 7 0 obj << /Type /Page /Parent 3 0 R /Contents 8 0 R /Resources 4 0 R >> endobj 8 0 obj << /Length 890 /Filter /FlateDecode >> stream xœµWMoÔ0½çWø‡NíñøëÚ *»Ä¡j ¢Ú-‚ÿžñG’Ùì&46í˼±ã—çñĨ+eÔ½úѽçßùã‡7êrÓiˆ”¼n.ßñÝàÔ¯îßÒZY¾|VZÝvF]ñï¾3åþ[þÀ,©½"à±ÁÚLã $_ .¦‘P¡  N Í@hP\‚@#¡BA°ü°äBƒ’à ˜8*2’WY¡$Èu2B–K+y•*7mŸ¥¥÷€´ å?­¤ˆŸrŒŸÖQÄOÊ8ÆO«(â'EãÛæÚ›Çz>Þ¥€­”Ê™ì¬y¥Z|V¨Ÿ×©Ågeªñy•Z|V¤ë“®V<%“uMÑ.T Åä\ˆÐ,– Å|äjàõB ZÎæ×‘âbZÌ·h!†ù*´œ\> ÊÐb:YÞÎס™dãÁå…s!ôµ” /;©fózj›1 ?§ÉEëçú¨d«åyzyÍ{È€5¢ ˜6XüÌ1÷ˆM;Á»[>L‰]ʇ¸Ï=Ç#»´âÄÊéØB2S^æ›Ä V~™ï³:.1¶ÁøcL|˜s+ÔQ(î›Å›A®Á‰ÛÖ¾*X? qw Ú˜Àd˜§ou—Eó”Ä)6>•RÒ!ê<÷1vÙF¼¨À5Çãü0y<ËóeQ¦ØÖRÖ‘+O=űV¢^“(*qy E«ü_sQ~}®‘x×ct.Û5»„²üG˜í¬cy‹E©)6ÉZñçð¦|süÿÝb=¯‹;«ó–å4º…&ïUºfßµî¤}õ°ÿÚêéCØ“7Osa±k÷Gm Šendstream endobj 9 0 obj << /Type /Page /Parent 3 0 R /Contents 10 0 R /Resources 4 0 R >> endobj 10 0 obj << /Length 1746 /Filter /FlateDecode >> stream xœ½ZÍ5 ¿¿¿"G84Mì|^[Q¤J Á>‰â€J‹¨vA´Hˆÿ;“ÌîìîŒßƒÃμÌÄççgÇ^«Þ*«>ª?Oß]ïOmL½xã¦Û§÷êõûéåçï¿~¥Þ}>YzhÔ|ýü®¿~}³ñúæõ·ü4ª¿O?þ¤ŒúådÕ[úûx²e¸oNO ýjÑQGThu¶ sÒÖ(‚ö†Fg5_YÃ'å?<7£=Ž ˜{¨ß¶6kêîäh”´´oO7­XÝ­=: ÍÓèÐÚS‡t2S‡Ú\Êpthmî£6¡p×ZŽ€h*ÚµwËûÖœ:@LÚÀÒ¡5§è§Y:´æ<ÄÊ ªÂ5Ú¡omŽùØàut¦µ=aêi)ÄimOyZ»dÊWqK‡Z”PJ#4rÀVN§6m›ºšMAgÉèMœ,ÏK©ˆÙˆB—.îŒÈ-ž¹’&îh@·àýöv%¶KÌ|Ú)@¼ÿt€ÒEg^Ù . N‰É“˜É‘ÎNA°@-ÄK²ÓG#Dš·äô°Dx%ot Ÿ¢ 4î¢O¢8£óiÌ:^pb¶^dp‹xù’ÎhÞˆx ºÎhžZòø,G´ˆžÓ³r>Q®¢¢ËÛ¹µíìaqš«xMˆ94–”2ò•“ÚKvÔ°³¾ fbaÎH·l(ßgt[B™Ó7‘Ó¯- tóü½–O:ÍDþ^OÆÂê5ºu¤ïz+Ç΃/uM{ E†ötÐs0i¡¦“›öe²fhω¶†öh"îí-Æ:û®½ó¼C{º…дߊ¿íSIÇßÓžÅMÚ“QÚsæ6LØ~½Ÿ°·Ñpúh`r›MKíÓVÅI{N¶—µ¸yÄ[®µçË {5bBä¥Ú{·Â8ôÚÓìÊèÝr ®°çµ*YòŽ}>N-Ú{dþ`å/­ŸñvÕ'4l~ãZêco îƼԺʥ4mA‡°7u/¿ÞŽË>~VÒ øê8_ؽ¢„¹ ƸE£æ˜$’ËoÌwpL‡¹–‰v$—2]‹è¸>¬#>(Ãq奢4×—J­¥¼] J«úÒx¿Ô“Vå¥ñ~)'­ªKãýRMZ—ŽÙE´•9Wv·ª_M«þzU¿šêUýýª|5•«úûUõjªVõ÷«âÕ Á…û…üòvçÝ}Èr-Y^2“äîÆ^Ò$éöJ"É?’a¯¤³–ƒƒ!™îï–§yÈ´¯õë Wk×#Ö6Å"m¡^ïûë·»÷÷=0ÈôåÓ€d˜JðÒ²[ÿ<7±õÞxô¿8Ëˤf#/÷Èúr)ç”ÿÕár®H9åëLôÏ·¿þ±5›ù¿ŠƒתyýR¬…”¢½®4Ÿ¿²Qö¨c_ýw¦ŽçbF_˜Œ›5€ úÚEÎ:8_~pˆ¤ÉÖ³´oÕÍQ<} )öà¹U#šæ²Y^ÏPB°]x‰nC–ü]²µ-@ÖNÚîAv+Ù<Íj+ê½ ²jÃÖÑlÙ#‘÷cȺrÈÖ¶Yâàv!»•¶šfµ‘_Y Ô7óÈ9<†,ÎLÈÖöŒ¬€Ñ7=n´|~‚dzúŽéÜ>å®4"±@K¡ðˆÂâÿ`DÚÎ/#âÿ0"¤^ÁåÝ^Ÿ•¿Ó¿m—Cendstream endobj 11 0 obj << /Type /Page /Parent 3 0 R /Contents 12 0 R /Resources 4 0 R >> endobj 12 0 obj << /Length 1693 /Filter /FlateDecode >> stream xœÍY]o\5}ß_áGxˆñøãÚ~MH•@‚D„x(ý­nJ¡• ÿžçÞq²ÝìfwSv£=c{æøØ æ©óÆüµùááã¬sÆ'O’‹ ýýÒüdÞn¾zÿã·—æùû à?ÑßïŸKó“«-ÍWO¾§ÿfóÏæ×ߌ3/6`žâçÍš×ï6;_.1†`s0¾[ÁÄ)Ú\ ¤ls¼¤³Õ{£¿)ÈݼºoΦ°NÂÝšD¼z›&s³‰µØäÏ›«nb´Þ­+ƒšl‰Ê€1€Ëv™ÀàÁN©Yx£®+‹ª­yµèXYÄ2Y˜V‹Ž•Ÿ›=l(66c5¯Œ å•ãÕ zt –®ãR´IÍ›¡ÇÊN- c½0u²¥¨…a¬§íMkuÂxœ6î´Sß-© . .yż¥m 5[p‚gÁÁ§Û/øL<À,ÁÅŠ¬­6VÁó‚½³!6Ìö‚iŒ“u ÇͶNmc=m[Çó‚!Ñ´æÅ^p‹êliq ƒ˜Ï Æœ¯-Žn/˜ã(6ãöúh'ßâHÔ¹ãyÁhÓçÅ^0q“µÏ嵦‚àˆÖïÆWßxdÍëW¦Ú¾›üÕ ¦nŠmep‡®oÌð¥¹~³ùúº¼««oõ¦‰þPWwXψ¾ch=Ÿ2«…ž2u]¿ïrìzr-ë¤J‡¢m5ÈíR¤CÍ®íK%KíûnÍQ“ÀÒÉ ôŠx Œ¼0ð@·yaàq2ð‚žê‘Y*­½ÏžÈî°,ƒ©Ð¡¡úîŸfÈK£Û½½ÝàY¦ºúÛ)º»·Ñçâ`tÉØOÈ0¸útJ¹æóßÛ>ð¡¾PþˆÅ -.½÷ÍkÌæOª"UC<Ô‹çt"q[×õÆéW+ ·âQ=y›K›É‡ï^n›ŒVJ”þnã€õŠu¨‘²õ¥ßšþíhý„]Hi…^lsÏ žŒUꉅÄ^ð¶£à€5Úšþ%ÚR[‰óéõÛ×öÙîC6'ÜÚœ†;eâñ|4ü|až½}a~¹¸z÷ìùÖ]:ÁG…Ñ5õãéú‹¾WYŸ€ ¤W@±ÛR-Ù{ªúýõ<6^|¢ü1C: ¸¹;…µ™áÚ HÖöŽ•ª…P•ãÕÀ»VÏ‹AÇw¥x_ Ìôiµf¸ŽFk×f†*¤’âU4Œ•A,|ƒÆÊk,éù0ná¢-·¼Y7=jÔàwhl*ÚÔ67Ó¸HÒv8wH‹R) 6^`ÓµæÑPéÑÌÛñ™:œ¢hÛÚ²>OÄã€|Å;ƒÇ*x^0j†ÌúœíÓü¯€[Û”5÷`8 Œ÷‚mµ‰}6$hbjSè5<¯8óus±ï˜Æ¸ËZT>à%RêçÆt([böWvç㉒°©$¬X·¿ÜÁŒ¬ ž+Ô›'~Xop…ò·w?Ø9 LÅvëðŽI’tWÞO£¨ ƒÂš?ø)€Z…04}¬­ _ ô¡Ú….öPíÂy<Ú•B(¨öƒ&¨Š}@*$Ùíîö³IgÀ}̨:E8¿øó÷sIg¼EåíòüÒ™ž…=–?èç—΀Ž&îxQÄÝ~PÈ1zz•Mxd´ÙÄgx/)SƒÍX`ëï"½Rµ7ÀÓ£7ÃY ëH«Ý¶þ˜l™ˆÕ¨;¶ÎñfµÁf,ðÓÚ–.ÛJÛvøÿѶå;‰Û` ô'Àƒô%wÇëKˆÒý}ÉÝéîQÊC´uM bFÿuÝûc:Ö´E^ŸDßçšÂíÌ1 WukæˆDµ/Ì12‰¶æ™D[sŒLòx¯çºÔØê¤ïÚå±¥n¨p~©ëû{Õº§z&8òcj]úYç$Z7Я'GkÝè`кÑÕAë m+ögÔºêç׺÷6ÿsMÿ/endstream endobj 13 0 obj << /Type /Page /Parent 3 0 R /Contents 14 0 R /Resources 4 0 R >> endobj 14 0 obj << /Length 2080 /Filter /FlateDecode >> stream xœÍZËn[7Ýë+î²]˜%‡ïm‚6@€hm -Š.Ò<š×Išhó÷’—CY–%ùÚÎBJN8äÌðq8GŒ™žNfz;ý³ùùôϤ•Öx ?¼v}|9ý:½Û|÷é—'¦çŸ6ÿQOòûÓóÖüø|GóùãŸè_ãôïæ?'=½Ø˜é)~Þn {ýq³×ù£%FkU´$«²™\p*æÉø¨¢»¤V`’ßäþ^Ý”„VÞö$ôVuð ʇérãrRž7çÕÀ:§@wƒŠ…Aö*9aP0U0-ˆ3*x¶#w‹Š……õYåØ-*.eB·¨XXŒ«YÃ6IÙ$Â.Xäq¢@Ü  1usHNy‘w2 +j11ˉÉA¥$&¦`™6XJ«;)XX|÷ä|œþng@‹oÞ^ §'?㦴9*£ž¶Ú(C#Vû¿Æ-hp¿à´9cXÊ$gårÃó‚A+ëû†i ë¼ÒÇ*^b ¬x^°ñ”à¼Ø7Ìq CK}¬J:p±áyÁ¸û3ÇQí.q$q¡Á©‡§ÎÏ ¶†–^ì¦1xÎ͹§±Ï¹óIœC ´à¸jTNìÃÃy«œî˜Æ¼OòçÑ…KPŽÕD6ý›yñ@v¾x5eUã._ ñˆxÇóŽëq9}sf¾.Þn¾¿`ûºŸkýA]õq=úv–{.>[~˜œé©!jd(¢_åô+t¨yo7VH‚Ï|io¤0pDo_8a j?t±VI¦ñÔ¸ðOeŠªÁÈGÿT‹‘þiN>’)¯¶ÿl¦Õ€D·Çí?][¢ïáùpt{°W¢9¼MEWØÞ¼‡Ö]¾ø6ft^0ä8\º15{ÿoÛûIÞ„‹3á™™, (õËM¹Š=¿Âîª ðJ¼ÚñBÀ:Â.…W¶Dw9™ÈñuLœÞç/^îÊp§ÇŒ— üællÙ$x%h,ì0µT¿‡d®í Ï9äpÙË™õ†ö|Åó‚ñ°‘Z³oøõ~§×$ñô§$±û‚„•¥ €Všˆ(zJ‚‹H¸öºã]äI˾óè¼Ú;óå½y÷æó¾m½škª²¨hì®?||ÿáuÚ¦·[›žq½Å°î3åÖþílzöîÅôûÙù‡gÏwîþ>"Œ*«¶¤Ý¡tqå.=Eì퉦k=:ZTÑÝgPñ)ðTÃ]ônÑ·w¤W‡æ´_û˜†gžp®§éâ.Íx±Ý› ìÍ ¶·W, ÞP‰tƒ‚…ÞÉ! ƒ‚… (B¨˜ ð–1Pgé²"º,Ô'•r¿é+†Ò`Xó:çHa¡{+°G"1ÜÒ\`oÆɘÞ\ È°jv"—‚…w¤rºAÁÂ++#¨˜³1YAîé(Ò‹ÊÛ- ƒ›´"E£i‰4õ@ÈŒÆ6ˆÓkf.ß2s»Ëú)òHæÚ&:ú Á®f‚WÖw|cÐk;Y]#úaØ™‰÷+ÏMrôû„p}¨<_S(W%úµHå½áˆwQm×Ëû‡ZI-W'Xš±œ­Ï}–Ÿþ¹=yz¹YÚ íôeÄK ¬dRK‹Äçª[¤zÎЀ”Ä ‰ç¬–š¸Âk5q›Z.ý´ê˜%"ÔìÚööeÄTŒ"â‚¥r‰­K ú1PŽQ°° ,X¶gì‚Ù"©+”óRæp™—ÐÆ6i’MSZÔ¬¨›¦¬°‰Èj,5¥õèJóö´ú6ðã_ÅsÀ3—5¿C²ý‚yŒIëz]*gY8/o~È­ÆRgÝBØÁñöÂ[=¥ çâÂP‡f\!ûÏ™RÉŸš_áÜ âÁðÃ27xлiY> endobj 16 0 obj << /Length 2449 /Filter /FlateDecode >> stream xœÍZK·¾Ï¯ècrXšÅ7¯2 Ù’ ÈÁYI‘…^YÖHüïS’]=ÍÎŒzg}˜Ùý†EV±ºX¯&LßO0½Ÿ~ÞýåòÏdµ“‹ŽþDúôfúÛôa÷Íw·.–é?»oÿúÝ«éþq8l'ýýxÏ„°}{{€ìöÛ?Ó¯yúïîŸÿšìôzÓ÷øy¿–ãO»£â¼R{o²Ÿ\ñ¦ÂR0¹N³ÉáˆØÖTç&ýMb_êí©Û²&úe[vo[Iu&¦éaj1Ñu<ïnÁ8»4¬j4%(ÁD6›}#‡&E¦p´F](V>VSóBѰ¢%H EÊbý|›ØPŒ/JlÁj_åà… 8d T×0‹LTû¨µ²UЬS“)E)F°Þ¶ó´­…‰`EÁöVÉPÄ&¬úf3+¨JT~E›¦èk6`;ž;ö Њ~àwhŠ€ö‚j àó´“ZM¨Ï;k|`,ôÓ>Dc#®›MMüˆ=À†ç!ÒçAß1Ë =Íñ¦°È äŽçÑú+ËÑè;9ŠÉø ]0ɱ‘&7<ìÿ<è;~'GÓ%K:×Ú^<Ò4…ˆËѪ¨ÜŒ\Ô/ÕšUL¤:ï-Y,jG÷D¬0Æ[ès;âµ…ºý :—>MwÔ×ÄÔworÉÜ•Ü÷»·ÊŸé].ö•ÑŽðâiA xØåbJÄ'Ťj\^ )ï+‚^Ýö±Þ’w]¾94üÑa¨º{;UÓ„–/†è b`CC¿{˜~w¿ŸîÞïþpÇ<ŽMuìÀ|Jô‡¦Úófä<Ï<ûþ>óûuGK,ߟ‡³Ïü¾åCÜÝßʲs“ñîýVÎpÎoå iüÔ‡µÉfº£9K+¿»r´`íxW޶Q¬ïÊÑv&+Ç«·¼™ýùJOÃeGqå<ûƒTè@©¹§ :þ5Û“¹’?Ç´AMuûÆ{êa=©o€5sÁ.¡3Ç'B©eîÿÛç~7ÅâFq¦ÐQðˆ#ƒúëS{U6Zâ %r¸Çȇ  «@6i\ËŸQ™P"cHÎäÂÛûå×oíðp>‹¾^G™BÅ‹™l6®´ïÕf¾¨ý8ç(ð|ìrf1úßñ<0vW }ÇïŽ3ýÂ&0G#»`‡3>RÐ mºû„ Ã#ÒÉ?õÀ{òÀa¦gÀ¤{1á4ù½ÅØï.—?º{‹ÙÚ yÇEŒ,°dm˜zQ¢Þñ¡‘Ùt]=kefQ<À~üåØ±ÜŽu±’z Öo~¾ gfMNbáüñÓOOñE—¹ ¿ç.·ø¥H¾ó÷›é‡¯§ÜÜ~üáþ ßØà£Ähµø‹w ³ô°hἋ’Ln¨6‡M€³ÛGWÚ¨; <"VO\}†Dq] çD< 6ÑSã +t6±(ÁD€µÕ– Å« ‡Ÿ—,0ØY7ÆT´ñAƒz…Õ#y ïnˆ#P‰ëy‘E\ÁŠ “³"L5câÒÒ¤@!|ìG ÞÏôÇ~*‚§ªyLG-†Œq¬ñÊÞ¾Áy@ Ä´¡NÜ WÐèÏ1Hc–›É?968ˆ5í·7(¸3!N€šr²@%4<ŒGÃó¾cZP´ñÈÕµ‹0ñ Φ(ý ¡íˆg;2"•ª6Ô˜ÐáÜ!U¸$N#îð´Ú±Š§ ×ò‘k÷ö‹#Ù(ùvtªœu”ˆŽ‡Ìèž©“ a/Ôhsµµ…ºý’É Û\¨‘Û²vCBͼÇx“´ÍÕrŸR»7û ìVÈÞ· 2Y&Tx0’°+o_uvñŸ]ܦ¸ní•X³n82}å ¦=o0^t^©s¹.¾h'×n<\ím¸`6žXüÃ%˜ž½mÙí‹Ã›jßʾ’G‡3]ùV5Þ}éʵ^½ƒÐƒõ”$—¡ª‚âE ‹ãKmuŸA˜`¹ôKy†òÞŠÇ1=¶q¨Æ©,MŠ aMA7 4…`M‘×W"f \–¾FƒªÌ÷èÿÀ/½‡…¥ñÑà]÷~uWA ëh½'jœÞŠ©qzË’U,[¬)è}‰VŠ`MÙwÒ‚™"d.8»Vj­7$†Vj‚ÂQi<£¿â}!ùDMˆ¾„€õŠÀ¹C,m_âùv¥_…ë3Žž>ã&kÇó‚k»}Ñéæ5ȉÛ)&zCƒK8¾O#pî0yºé0wâÇ|j“Ëe š@×N’ÜÕh0z¹šÑˆ;äù‘ÛA(_²ð‘û?ç‹\©èÄe¹aqÂíºÔQ¨€¶ —#Ú|$`bžp'©=c|{An£Ž;m^¼ªÊNŸÇý¨¾*&m<Û¨H#󴬧4U†Ñj{z×xš"•Ækà’üt_¥KÛÔÕ´6ËÓ}•µ³™öœÍo©¯â¨‘‰Ç×öË7X©ŸÞiÓ“£¾Q›~Fk¥M¯|-†§Ûó¸£ã-ihþtV_¨Ïǃ^ Ï¿€?åžmþjû›6Tè=c´#à¬â8{qK-à¬âïgÔø8ë¤)zÀY MÑÎ:]½ÕÃYë"­‚ n}|ëTlã:Ô=ÏýŒvœ¶œÝ†"oÊ.æü+&%K¢óm(–‘ájm(‡Ça݇ÚþŠ …w2šhDy—Ø|6ìDÑQ_·kEù˜)m]!Ÿ½H]¡Ž{¨ÓU+ê™™~Asô&Ìo׊ è[s^ºDÁFî°÷®Ý§FôWµ¢6grH3Áó¥Èkµ¢V íT\¥u*¿Í›2>ó½Ú—hEÀ »¾H+ŠnbSüzžVÔîÿŒÅ·áendstream endobj 3 0 obj << /Type /Pages /Kids [ 7 0 R 9 0 R 11 0 R 13 0 R 15 0 R ] /Count 5 /MediaBox [0 0 504 504] >> endobj 4 0 obj << /ProcSet [/PDF /Text] /Font << /F1 18 0 R /F2 19 0 R >> /ExtGState << /GS1 20 0 R /GS2 21 0 R /GS257 22 0 R /GS258 23 0 R /GS259 24 0 R /GS260 25 0 R >> /ColorSpace << /sRGB 5 0 R >> >> endobj 5 0 obj [/ICCBased 6 0 R] endobj 6 0 obj << /Alternate /DeviceRGB /N 3 /Length 2596 /Filter /FlateDecode >> stream xœ–wTSهϽ7½P’Š”ÐkhRH ½H‘.*1 JÀ"6DTpDQ‘¦2(à€£C‘±"Š…Q±ëDÔqp–Id­ß¼yïÍ›ß÷~kŸ½ÏÝgï}ÖºüƒÂLX € ¡Xáçň‹g` ðlàp³³BøF™|ØŒl™ø½º ùû*Ó?ŒÁÿŸ”¹Y"1P˜ŒçòøÙ\É8=Wœ%·Oɘ¶4MÎ0JÎ"Y‚2V“sò,[|ö™e9ó2„<ËsÎâeðäÜ'ã9¾Œ‘`çø¹2¾&cƒtI†@Æoä±|N6(’Ü.æsSdl-c’(2‚-ãyàHÉ_ðÒ/XÌÏËÅÎÌZ.$§ˆ&\S†“‹áÏÏMç‹ÅÌ07#â1Ø™YárfÏüYym²";Ø8980m-m¾(Ô]ü›’÷v–^„îDøÃöW~™ °¦eµÙú‡mi]ëP»ý‡Í`/в¾u}qº|^RÄâ,g+«ÜÜ\KŸk)/èïúŸC_|ÏR¾Ýïåaxó“8’t1C^7nfz¦DÄÈÎâpù 柇øþuü$¾ˆ/”ED˦L L–µ[Ȉ™B†@øŸšøÃþ¤Ù¹–‰ÚøЖX¥!@~(* {d+Ðï} ÆGù͋љ˜ûÏ‚þ}W¸LþÈ$ŽcGD2¸QÎìšüZ4 E@ê@èÀ¶À¸àA(ˆq`1à‚D €µ ”‚­`'¨u 4ƒ6ptcà48.Ë`ÜR0ž€)ð Ì@„…ÈR‡t CȲ…XäCP”%CBH@ë R¨ª†ê¡fè[è(tº C· Qhúz#0 ¦ÁZ°l³`O8Ž„ÁÉð28.‚·À•p|î„O×àX ?§€:¢‹0ÂFB‘x$ !«¤i@Ú¤¹ŠH‘§È[EE1PL” Ê…⢖¡V¡6£ªQP¨>ÔUÔ(j õMFk¢ÍÑÎèt,:‹.FW ›Ðè³èô8úƒ¡cŒ1ŽL&³³³ÓŽ9…ÆŒa¦±X¬:ÖëŠ År°bl1¶ {{{;Ž}ƒ#âtp¶8_\¡8áú"ãEy‹.,ÖXœ¾øøÅ%œ%Gщ1‰-‰ï9¡œÎôÒ€¥µK§¸lî.îžoo’ïÊ/çO$¹&•'=JvMÞž<™âžR‘òTÀT ž§ú§Ö¥¾N MÛŸö)=&½=—‘˜qTH¦ û2µ3ó2‡³Ì³Š³¤Ëœ—í\6% 5eCÙ‹²»Å4ÙÏÔ€ÄD²^2šã–S“ó&7:÷Hžrž0o`¹ÙòMË'ò}ó¿^ZÁ]Ñ[ [°¶`t¥çÊúUЪ¥«zWë¯.Z=¾Æo͵„µik(´.,/|¹.f]O‘VÑš¢±õ~ë[‹ŠEÅ76¸l¨ÛˆÚ(Ø8¸iMKx%K­K+Jßoæn¾ø•ÍW•_}Ú’´e°Ì¡lÏVÌVáÖëÛÜ·(W.Ï/Û²½scGÉŽ—;—ì¼PaWQ·‹°K²KZ\Ù]ePµµê}uJõHWM{­fí¦Ú×»y»¯ìñØÓV§UWZ÷n¯`ïÍz¿úΣ†Š}˜}9û6F7öÍúº¹I£©´éÃ~á~éˆ}ÍŽÍÍ-š-e­p«¤uò`ÂÁËßxÓÝÆl«o§·—‡$‡›øíõÃA‡{°Ž´}gø]mµ£¤ê\Þ9Õ•Ò%íŽë>x´·Ç¥§ã{Ëï÷Ó=Vs\åx٠‰¢ŸN柜>•uêééäÓc½Kz=s­/¼oðlÐÙóç|Ïé÷ì?yÞõü± ÎŽ^d]ìºäp©sÀ~ ãû:;‡‡º/;]îž7|âŠû•ÓW½¯ž»píÒÈü‘áëQ×oÞH¸!½É»ùèVú­ç·snÏÜYs}·äžÒ½Šûš÷~4ý±]ê =>ê=:ð`Áƒ;cܱ'?eÿô~¼è!ùaÅ„ÎDó#ÛGÇ&}'/?^øxüIÖ“™§Å?+ÿ\ûÌäÙw¿xü20;5þ\ôüÓ¯›_¨¿ØÿÒîeïtØôýW¯f^—¼Qsà-ëmÿ»˜w3¹ï±ï+?˜~èùôñî§ŒOŸ~÷„óûendstream endobj 17 0 obj << /Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences [ 45/minus 96/quoteleft 144/dotlessi /grave /acute /circumflex /tilde /macron /breve /dotaccent /dieresis /.notdef /ring /cedilla /.notdef /hungarumlaut /ogonek /caron /space] >> endobj 18 0 obj << /Type /Font /Subtype /Type1 /Name /F1 /BaseFont /ZapfDingbats >> endobj 19 0 obj << /Type /Font /Subtype /Type1 /Name /F2 /BaseFont /Helvetica /Encoding 17 0 R >> endobj 20 0 obj << /Type /ExtGState /CA 1.000 >> endobj 21 0 obj << /Type /ExtGState /CA 0.298 >> endobj 22 0 obj << /Type /ExtGState /ca 0.502 >> endobj 23 0 obj << /Type /ExtGState /ca 1.000 >> endobj 24 0 obj << /Type /ExtGState /ca 0.333 >> endobj 25 0 obj << /Type /ExtGState /ca 0.667 >> endobj xref 0 26 0000000000 65535 f 0000000021 00000 n 0000000163 00000 n 0000009840 00000 n 0000009950 00000 n 0000010154 00000 n 0000010187 00000 n 0000000212 00000 n 0000000292 00000 n 0000001253 00000 n 0000001334 00000 n 0000003153 00000 n 0000003235 00000 n 0000005001 00000 n 0000005083 00000 n 0000007236 00000 n 0000007318 00000 n 0000012882 00000 n 0000013140 00000 n 0000013224 00000 n 0000013322 00000 n 0000013371 00000 n 0000013420 00000 n 0000013469 00000 n 0000013518 00000 n 0000013567 00000 n trailer << /Size 26 /Info 1 0 R /Root 2 0 R >> startxref 13616 %%EOF ParamHelpers/tests/testthat/test_dropParams.R0000644000176000001440000000060213633666270021173 0ustar ripleyuserscontext("dropParams") test_that("dropParams", { ps = makeParamSet( makeNumericParam("u", lower = 1), makeIntegerParam("v", lower = 1, upper = 2), makeDiscreteParam("w", values = 1:2) ) expect_equal(getParamIds(dropParams(ps, "u")), c("v", "w")) expect_equal(getParamIds(dropParams(ps, c("u", "v"))), "w") expect_true(isEmpty(dropParams(ps, c("u", "v", "w")))) }) ParamHelpers/tests/testthat/test_plotYTrace.R0000644000176000001440000000152013633666270021151 0ustar ripleyuserscontext("plotYTrace") test_that("plotYTrace works", { makeArtOP = function() { ps = makeNumericParamSet(len = 1L) op = makeOptPathDF(par.set = ps, y.names = "y", minimize = TRUE, include.exec.time = TRUE) X = rnorm(40) dob = c(rep(0, 5), rep(1:7, each = 2), 8) for (i in 1:20) { addOptPathEl(op, x = list( x = X[i * 2]), y = X[ i * 2 - 1], dob = dob[i], exec.time = rexp(1)) } op } # build aritificial list of opt pathes opt.paths = list( algo1 = makeArtOP(), algo2 = makeArtOP(), algo3 = makeArtOP(), algo4 = makeArtOP()) pl = renderYTraces(opt.paths, over.time = "dob") expect_is(pl, "gg") expect_is(pl, "ggplot") pl = renderYTraces(opt.paths, over.time = "exec.time") expect_is(pl, "gg") expect_is(pl, "ggplot") plotYTraces(opt.paths) }) ParamHelpers/tests/testthat/test_ParamSet.R0000644000176000001440000002041013633666270020576 0ustar ripleyuserscontext("ParameterSet") test_that("empty paramset", { ps = makeParamSet() expect_equal(getParamIds(ps), character(0)) expect_equal(getParamLengths(ps), integer(0)) expect_equal(getLower(ps), numeric(0)) expect_equal(getUpper(ps), numeric(0)) expect_equal(getValues(ps), list()) expect_output(print(ps), "Empty parameter set.") expect_true(isEmpty(ps)) }) test_that("mixed paramset", { ps = makeParamSet( makeNumericParam("u", lower = 1), makeIntegerParam("v", lower = 1, upper = 2), makeDiscreteParam("w", values = 1:2), makeLogicalParam("x"), makeDiscreteVectorParam("y", len = 2, values = c("a", "b")) ) expect_equal(getParamIds(ps), c("u", "v", "w", "x", "y")) expect_equal(getParamLengths(ps), c(u = 1L, v = 1L, w = 1L, x = 1L, y = 2L)) expect_equal(getLower(ps), c(u = 1, v = 1L)) expect_equal(getUpper(ps), c(u = Inf, v = 2L)) values1 = list(1, 2) names(values1) = 1:2 values2 = list("a", "b") names(values2) = c("a", "b") values3 = list(TRUE, FALSE) names(values3) = c("TRUE", "FALSE") expect_equal(getValues(ps), list(w = values1, x = values3, y = values2)) expect_output(print(ps), "u\\s*numeric") }) test_that("mixed paramset 2", { p1 = makeNumericParam(id = "x1", lower = -1L, upper = 1) p2 = makeNumericParam(id = "x2", lower = 0, upper = Inf) p3 = makeDiscreteParam(id = "x3", values = list(a = "char", b = 2L, c = 2.2, "e")) ps = makeParamSet(p1, p2, p3) expect_true(isFeasible(ps, list(0, 0, "char"))) expect_true(!isFeasible(ps, list(2, 0, "char"))) expect_equal(getLower(ps), c(x1 = -1, x2 = 0)) expect_equal(getUpper(ps), c(x1 = 1, x2 = Inf)) expect_true(isFeasible(ps, list(x3 = 2L, x1 = 0), filter = TRUE)) }) test_that("cannot build param set from wrong stuff", { expect_error(makeParamSet(1), "Param") expect_error( makeParamSet( makeNumericParam("x"), makeNumericParam("x") ), "unique" ) }) test_that("paramset with vector", { ps = makeParamSet( makeNumericParam("x", lower = 1), makeIntegerVectorParam("y", len = 2, lower = 3L, upper = 9L) ) expect_equal(getParamIds(ps), c("x", "y")) expect_equal(getParamLengths(ps), c(x = 1L, y = 2L)) expect_equal(getParamIds(ps, repeated = TRUE, with.nr = FALSE), c("x", "y", "y")) expect_equal(getParamIds(ps, repeated = TRUE, with.nr = TRUE), c("x", "y1", "y2")) expect_equal(getLower(ps), c(x = 1, y = 3L, y = 3L)) expect_equal(getUpper(ps), c(x = Inf, y = 9L, y = 9L)) expect_true(is.list(getValues(ps))) expect_equal(length(getValues(ps)), 0) expect_output(print(ps), "x\\s*numeric") }) test_that("list works", { ps = makeParamSet(params = list( makeNumericParam("u", lower = 1), makeIntegerParam("v", lower = 1, upper = 2) )) expect_equal(getParamIds(ps), c("u", "v")) expect_output(print(ps), "u\\s*numeric") }) test_that("combination with c works", { ps1 = makeParamSet( makeNumericParam("u", lower = 1), makeIntegerVectorParam("v", len = 2, lower = 3L, upper = 9L) ) ps2 = makeParamSet( makeDiscreteParam("w", values = 1:2), makeLogicalParam("x") ) # ps with "difficult" name ps3 = makeParamSet( makeNumericParam("params") ) ps = c(ps1, ps2) expect_equal(length(ps$pars), 4) expect_equal(getParamIds(ps), c(getParamIds(ps1), getParamIds(ps2))) ps = c(ps1, ps3) expect_equal(length(ps$pars), 3) expect_equal(getParamIds(ps), c(getParamIds(ps1), getParamIds(ps3))) }) test_that("cannot combine with overlapping names", { ps1 = makeParamSet( makeNumericParam("u") ) ps2 = makeParamSet( makeDiscreteParam("u", values = 1:2) ) expect_error(c(ps1, ps2), "unique") }) test_that("unknown length works", { ps = makeParamSet( makeNumericLearnerParam("u", lower = 2), makeNumericVectorLearnerParam("v", len = NA, lower = 1) ) expect_equal(getParamLengths(ps), c(u = 1, v = NA)) expect_true(isFeasible(ps, list(3, c(2)))) expect_true(isFeasible(ps, list(3, c(2, 4)))) expect_false(isFeasible(ps, list(3, c(2, 0)))) expect_error(sampleValue(ps), "Cannot sample") }) test_that("makeNumericParamset", { ps = makeNumericParamSet(lower = 10, len = 2, vector = TRUE) expect_equal(getParamIds(ps), "x") expect_equal(getParamLengths(ps), c(x = 2)) expect_equal(getLower(ps), c(x = 10, x = 10)) expect_equal(getUpper(ps), c(x = Inf, x = Inf)) ps = makeNumericParamSet(upper = 10, len = 2, vector = TRUE) expect_equal(getParamIds(ps), "x") expect_equal(getParamLengths(ps), c(x = 2)) expect_equal(getLower(ps), c(x = -Inf, x = -Inf)) expect_equal(getUpper(ps), c(x = 10, x = 10)) ps = makeNumericParamSet(id = "y", upper = 3, len = 2, vector = FALSE) expect_equal(getParamIds(ps), c("y1", "y2")) expect_equal(getParamLengths(ps), c(y1 = 1, y2 = 1)) expect_equal(getLower(ps), c(y1 = -Inf, y2 = -Inf)) expect_equal(getUpper(ps), c(y1 = 3, y2 = 3)) ps = makeNumericParamSet(lower = c(1, 2), vector = TRUE) expect_equal(getLower(ps), c(x = 1, x = 2)) ps = makeNumericParamSet(lower = c(1, 4), upper = c(2, 7), vector = FALSE) expect_equal(getLower(ps), c(x1 = 1, x2 = 4)) expect_equal(getUpper(ps), c(x1 = 2, x2 = 7)) }) test_that("requires works", { ps = makeParamSet( makeDiscreteParam("x", values = c("a", "b"), default = "a"), makeNumericParam("y", requires = quote(x == "a")), makeIntegerVectorParam("z", len = 2, requires = quote(x == "b")) ) expect_true(isFeasible(ps, list(x = "a", y = 1, z = NA))) expect_false(isFeasible(ps, list(x = "a", y = NA, z = 1))) expect_false(isFeasible(ps, list(x = "a", y = NA, z = c(NA, NA)))) expect_false(isFeasible(ps, list(x = "b", y = 1, z = c(2, 2)))) expect_true(isFeasible(ps, list(x = "b", y = NA, z = c(2, 2)))) expect_true(isRequiresOk(ps, list(x = "a"))) expect_true(isRequiresOk(ps, list(x = "c"))) # out of bound is supposed to be ignored expect_true(isRequiresOk(ps, list(y = 1))) expect_error(isRequiresOk(ps, list(y = 1), use.defaults = FALSE)) expect_error(isRequiresOk(ps, list(y = 1, x = "b")), 'x == "a"') }) test_that("requires chains work", { ps = makeParamSet( makeLogicalLearnerParam("a", default = FALSE), makeLogicalLearnerParam("b", default = FALSE, requires = quote(a == TRUE)), makeLogicalLearnerParam("c", default = FALSE, requires = quote(b == TRUE)) ) expect_true(isFeasible(ps, list(a = FALSE, b = NA, c = NA))) expect_true(isFeasible(ps, list(a = TRUE, b = FALSE, c = NA))) expect_true(isFeasible(ps, list(a = TRUE, b = TRUE, c = FALSE))) expect_true(isFeasible(ps, list(a = TRUE, b = TRUE, c = TRUE))) }) test_that("print works", { ps = makeParamSet( makeIntegerParam("ntree", lower = 10, upper = 50), makeNumericVectorParam("cutoff", len = 3, lower = 0.001, upper = 1, trafo = function(x) 0.9 * x / sum(x)) ) expect_output(print(ps), "numericvector") expect_output(print(ps), "3") ps = makeParamSet( makeIntegerLearnerParam(id = "x", default = 50L, lower = 1L), makeNumericVectorLearnerParam(id = "v", default = 1:2, len = 2L) ) expect_output(print(ps, trafo = FALSE, used = FALSE), "numericvector") ps = makeParamSet( makeIntegerLearnerParam(id = "x", default = 50L, lower = 1L), makeNumericVectorLearnerParam(id = "v", default = 1:2, len = 2L), forbidden = expression(x < v[[1]]) ) expect_output(print(ps), "Forbidden region specified") }) test_that("expressions get converted", { ps1 = makeParamSet( makeLogicalLearnerParam("a", default = FALSE), makeLogicalLearnerParam("b", default = FALSE, requires = expression(a == TRUE)) ) ps2 = makeParamSet( makeLogicalLearnerParam("a", default = FALSE), makeLogicalLearnerParam("b", default = FALSE, requires = quote(a == TRUE)) ) expect_is(ps1$pars$b$requires, "call") expect_equal(ps1, ps2) expect_error({ ps = makeParamSet( makeLogicalLearnerParam("a", default = FALSE), makeLogicalLearnerParam("b", default = FALSE, requires = "a == TRUE") ) }, "call") }) test_that("test whether paramset fails gracefully", { li <- list( makeLogicalLearnerParam("a", default = FALSE), makeLogicalLearnerParam("b", default = FALSE, requires = expression(a == TRUE)) ) expect_error({ makeParamSet( makeLogicalLearnerParam("a", default = FALSE), makeLogicalLearnerParam("b", default = FALSE, requires = quote(a == TRUE)), params = li ) }, regexp = "You can only use one of \\.\\.\\. or params!") }) ParamHelpers/tests/testthat/test_convertDiscrete.R0000644000176000001440000000430513164130622022214 0ustar ripleyuserscontext("convertDiscrete") test_that("discrete param NameToValue", { f = function(x) 2 * x p = makeDiscreteParam(id = "x", values = list(a = "char", b = 2L, c = 2.2, d = f, "e")) expect_equal(discreteNameToValue(p, "b"), 2L) expect_equal(discreteNameToValue(p, "c"), 2.2) expect_equal(discreteNameToValue(p, "e"), "e") expect_error(discreteNameToValue(p, ""), "Names not used") p = makeIntegerParam(id = "y") expect_error(discreteNameToValue(p, "a")) # check that the operation works with very small values, we had a bug here in mlr#1115 p = makeDiscreteParam("x", values = c(a = 1e-8, b = 1e-9)) expect_equal(discreteNameToValue(p, "a"), 1e-8) expect_equal(discreteNameToValue(p, "b"), 1e-9) }) test_that("discrete param ValueToName", { f = function(x) 2 * x p = makeDiscreteParam(id = "x", values = list(a = "char", b = 2L, c = 2.2, d = f, "e")) expect_equal(discreteValueToName(p, 2L), "b") expect_equal(discreteValueToName(p, 2.2), "c") expect_equal(discreteValueToName(p, "e"), "e") expect_equal(discreteValueToName(p, f), "d") expect_error(discreteValueToName(p, 3), "Value not found") expect_error(discreteNameToValue(p, 2)) p = makeIntegerParam(id = "y") expect_error(discreteNameToValue(p, "a")) # check that the operation works with very small values, we had a bug here in mlr#1115 p = makeDiscreteParam("x", values = c(a = 1e-8, b = 1e-9)) expect_equal(discreteValueToName(p, 1e-8), "a") expect_equal(discreteValueToName(p, 1e-9), "b") }) test_that("discrete vec param NameToValue", { f = function(x) 2 * x p = makeDiscreteVectorParam(id = "x", len = 2, values = list(a = "char", b = 2L, c = c(2.2, 3.3), d = f, "e")) expect_equal(discreteNameToValue(p, c("a", "b")), list(a = "char", b = 2L)) expect_equal(discreteNameToValue(p, c("e", "b")), list(e = "e", b = 2L)) expect_equal(discreteNameToValue(p, c("c", "d")), list(c = c(2.2, 3.3), d = f)) }) test_that("discrete vec param ValueToName", { f = function(x) 2 * x p = makeDiscreteVectorParam(id = "x", len = 2, values = list(a = "char", b = 2L, c = 2.2, d = f, "e")) expect_equal(discreteValueToName(p, list(2L, "char")), c("b", "a")) expect_equal(discreteValueToName(p, list(2.2, f)), c("c", "d")) }) ParamHelpers/tests/testthat/test_generateDesign.R0000644000176000001440000002216513633666270022017 0ustar ripleyuserscontext("generateDesign") test_that("simple num design", { requirePackages("_lhs") ps1 = makeParamSet( makeNumericParam("x1", lower = -2, upper = 1) ) des = generateDesign(13, ps1, lhs::randomLHS) expect_equal(nrow(des), 13) expect_equal(ncol(des), 1) expect_true(is.numeric(des[, 1])) expect_true(all(des[, 1] >= -2) && all(des[, 1] <= 1)) des = generateDesign(13, ps1, lhs::maximinLHS) expect_equal(nrow(des), 13) expect_equal(ncol(des), 1) expect_true(all(des[, 1] >= -2) && all(des[, 1] <= 1)) }) test_that("simple num/int design", { requirePackages("_lhs") ps2 = makeParamSet( makeNumericParam("x1", lower = -2, upper = 1), makeIntegerParam("x2", lower = 10, upper = 20) ) des = generateDesign(13, ps2, lhs::randomLHS) expect_equal(nrow(des), 13) expect_equal(ncol(des), 2) expect_true(is.numeric(des[, 1])) expect_true(all(des[, 1] >= -2) && all(des[, 1] <= 1)) expect_true(is.integer(des[, 2])) expect_true(all(des[, 2] >= 10) && all(des[, 2] <= 20)) des = generateDesign(13, ps2, lhs::maximinLHS) expect_equal(nrow(des), 13) expect_equal(ncol(des), 2) expect_true(is.numeric(des[, 1])) expect_true(all(des[, 1] >= -2) && all(des[, 1] <= 1)) expect_true(is.integer(des[, 2])) expect_true(all(des[, 2] >= 10) && all(des[, 2] <= 20)) }) test_that("simple num/int/discrete/log design", { ps3 = makeParamSet( makeNumericParam("x1", lower = -2, upper = 1), makeIntegerParam("x2", lower = 10, upper = 20), makeDiscreteParam("x3", values = c("a", "b", "c")), makeLogicalParam("x4") ) des = generateDesign(500, ps3) expect_equal(nrow(des), 500) expect_equal(ncol(des), 4) expect_true(is.numeric(des[, 1])) expect_true(all(des[, 1] >= -2) && all(des[, 1] <= 1)) expect_true(is.integer(des[, 2])) expect_true(all(des[, 2] >= 10) && all(des[, 2] <= 20)) expect_true(is.factor(des[, 3])) expect_true(all(des[, 3] %in% names(ps3$pars[[3]]$values))) expect_equal(levels(des[, 3]), names(ps3$pars[[3]]$values)) expect_true(is.logical(des[, 4])) tab = as.numeric(table(des[, 3])) expect_true(all(tab > 140) && all(tab < 180)) tab = as.numeric(table(des[, 4])) expect_true(all(tab > 200) && all(tab < 300)) }) test_that("num/int/disc vec design", { ps4 = makeParamSet( makeNumericVectorParam("x", len = 2, lower = -2, upper = 1), makeIntegerVectorParam("y", len = 3, lower = 10L, upper = 20L), makeDiscreteVectorParam("z", len = 2, values = list(a = "a", b = list())), makeLogicalVectorParam("a", len = 2) ) des = generateDesign(13, ps4) expect_equal(nrow(des), 13) expect_equal(ncol(des), 9) expect_equal(colnames(des), c("x1", "x2", "y1", "y2", "y3", "z1", "z2", "a1", "a2")) expect_true(is.numeric(des[, 1])) expect_true(is.numeric(des[, 2])) expect_true(is.integer(des[, 3])) expect_true(is.integer(des[, 4])) expect_true(is.integer(des[, 5])) expect_true(is.factor(des[, 6])) expect_true(is.factor(des[, 7])) expect_true(is.logical(des[, 8])) expect_true(is.logical(des[, 9])) expect_true(all(des[, 1] >= -2) && all(des[, 1] <= 1)) expect_true(all(des[, 2] >= -2) && all(des[, 2] <= 1)) expect_true(all(des[, 3] >= 10) && all(des[, 3] <= 20)) expect_true(all(des[, 4] >= 10) && all(des[, 4] <= 20)) expect_true(all(des[, 5] >= 10) && all(des[, 5] <= 20)) expect_true(all(des[, 6] %in% c("a", "b"))) expect_true(all(des[, 7] %in% c("a", "b"))) expect_equal(levels(des[, 6]), c("a", "b")) expect_equal(levels(des[, 7]), c("a", "b")) }) test_that("num/int vec design with trafo", { ps5 = makeParamSet( makeNumericVectorParam("x", len = 2, lower = -2, upper = 1, trafo = function(x) 2^x), makeIntegerVectorParam("y", len = 3, lower = 10L, upper = 20L, trafo = function(x) 3L * x) ) des = generateDesign(100, ps5, trafo = TRUE) expect_equal(nrow(des), 100) expect_equal(ncol(des), 5) expect_equal(colnames(des), c("x1", "x2", "y1", "y2", "y3")) expect_true(is.numeric(des[, 1])) expect_true(is.numeric(des[, 2])) expect_true(is.integer(des[, 3])) expect_true(is.integer(des[, 4])) expect_true(is.integer(des[, 5])) expect_true(all(des[, 1] >= 1 / 4) && all(des[, 1] <= 2)) expect_true(all(des[, 2] >= 1 / 4) && all(des[, 2] <= 2)) expect_true(all(des[, 3] >= 30) && all(des[, 3] <= 60)) expect_true(all(des[, 4] >= 30) && all(des[, 4] <= 60)) expect_true(all(des[, 5] >= 30) && all(des[, 5] <= 60)) ps6 = makeParamSet( makeNumericVectorParam("x", len = 2, lower = 0, upper = 1, trafo = function(x) x / sum(x)), makeIntegerVectorParam("y", len = 2, lower = 10L, upper = 20L, trafo = function(x) 1:2), makeDiscreteVectorParam("z", len = 2, values = c("a", "b")) ) des = generateDesign(5, ps6, trafo = TRUE) expect_equal(nrow(des), 5) expect_equal(ncol(des), 6) expect_equal(colnames(des), c("x1", "x2", "y1", "y2", "z1", "z2")) expect_true(is.numeric(des[, 1])) expect_true(is.numeric(des[, 2])) expect_true(is.integer(des[, 3])) expect_true(is.integer(des[, 4])) expect_equal(des[, 1] + des[, 2], rep(1, 5)) expect_equal(des[, 3], rep(1, 5)) expect_equal(des[, 4], rep(2, 5)) # check that trafo can be switched off ps = makeParamSet( makeNumericParam("x", lower = -10, upper = -1, trafo = function(x) -x) ) des = generateDesign(10, ps, trafo = FALSE) expect_true(is.numeric(des$x) && all(des$x <= -1)) }) test_that("requires works", { ps = makeParamSet( makeDiscreteParam("x", values = c("a", "b")), makeNumericParam("y", lower = 1, upper = 2, requires = quote(x == "a")), makeDiscreteParam("z", values = 1:2, requires = quote(x == "b")) ) des = generateDesign(50, par.set = ps) vals = dfRowsToList(des, ps) oks = sapply(vals, isFeasible, par = ps) expect_true(all(oks)) ps = makeParamSet( makeDiscreteParam("x", values = c("a", "b")), makeNumericVectorParam("y", len = 2, lower = 1, upper = 2, requires = quote(x == "a")) ) des = generateDesign(50, par.set = ps) vals = dfRowsToList(des, ps) oks = sapply(vals, isFeasible, par = ps) expect_true(all(oks)) }) test_that("nested requires", { ps7 = makeParamSet( makeDiscreteParam("disc", values = c("a", "b", "c")), makeNumericParam("realA", lower = 0, upper = 100, requires = quote(disc == "a")), makeIntegerParam("intA", lower = -100, upper = 100, requires = quote(disc == "a")), makeDiscreteParam("discA", values = c("m", "w"), requires = quote(disc == "a")), makeNumericParam("realB", lower = -100, upper = 100, requires = quote(disc == "b")), makeDiscreteParam("discB", values = c("R", "NR"), requires = quote(disc == "b")), makeNumericParam("realBR", lower = 0, upper = 2 * pi, requires = quote(identical(discB, "R") && identical(disc, "b"))), makeNumericParam("realBNR", lower = 0, upper = 2 * pi, requires = quote(identical(discB, "NR") && identical(disc, "b"))) ) des = generateDesign(50, par.set = ps7) expect_true(all(is.na(des[des$disc == "a", 5:8]))) expect_true(all(is.na(des[des$disc == "b", 2:4]))) expect_true(all(is.na(des[des$disc == "c", 2:8]))) expect_true(all(is.na(des[des$disc == "b" & des$discB == "NR", 7]))) expect_true(all(is.na(des[des$disc == "b" & des$discB == "R", 8]))) vals = dfRowsToList(des, ps7) oks = sapply(vals, isFeasible, par = ps7) expect_true(all(oks)) }) test_that("requires chains work", { ps8 = makeParamSet( makeLogicalLearnerParam("a", default = FALSE), makeLogicalLearnerParam("b", default = FALSE, requires = quote(a == TRUE)), # FIXME: shouldn't need to make the chain explicit makeNumericLearnerParam("c", lower = 0, upper = 1, requires = quote(b == TRUE && a == TRUE)) ) des = generateDesign(4L, par.set = ps8, augment = 100L) vals = dfRowsToList(des, ps8) oks = sapply(vals, isFeasible, par = ps8) expect_true(all(oks)) }) test_that("we dont drop levels in factors", { ps = makeParamSet( makeDiscreteParam("x", values = letters[5:1]) ) des = generateDesign(1, ps) expect_true(is.factor(des$x) && all(levels(des$x) == letters[5:1])) }) test_that("list of further arguments passed to lhs function produces no error", { ps = makeParamSet( makeDiscreteParam("x", values = c("a", "b", "c")), makeNumericParam("realA", lower = 0, upper = 100) ) des = generateDesign(10L, ps, fun.args = list(preserveDraw = TRUE)) expect_data_frame(des) }) test_that("removing duplicates", { # this param set has 6 possilbe combinations of param values ... ps = makeParamSet( makeIntegerParam("int", lower = 0, upper = 1), makeDiscreteParam("disc", values = letters[1:3]) ) # ... and therefore creating a design with n > 6 duplicate free rows should fail expect_warning(res <- generateDesign(7L, ps)) expect_true(nrow(res) <= 6L) }) test_that("vector params and forbidden regions", { # here we have a parameter set with a vector parameters ps = makeParamSet( makeNumericVectorParam(id = "x", len = 2, lower = 0, upper = 1), makeDiscreteParam(id = "disc", values = letters[1:2]), forbidden = expression(sum(x) > 1) ) # the expression in 'forbidden' should not throw an error anymore # See https://github.com/mlr-org/ParamHelpers/issues/51 res = generateDesign(100L, ps) expect_equal(nrow(res), 100L) expect_numeric(rowSums(res[, c("x1", "x2")]), lower = 0, upper = 1) }) ParamHelpers/tests/testthat/test_getParamNr.R0000644000176000001440000000076413633666270021134 0ustar ripleyuserscontext("getParamNr") test_that("getParamNr", { ps = makeParamSet() expect_equal(getParamNr(ps), 0L) expect_equal(getParamNr(ps, devectorize = TRUE), 0L) ps = makeParamSet( makeNumericParam("u", lower = 1), makeIntegerParam("v", lower = 1, upper = 2), makeDiscreteParam("w", values = 1:2), makeLogicalParam("x"), makeDiscreteVectorParam("y", len = 2, values = c("a", "b")) ) expect_equal(getParamNr(ps), 5L) expect_equal(getParamNr(ps, devectorize = TRUE), 6L) }) ParamHelpers/tests/testthat/test_trafo.R0000644000176000001440000000576413633666270020214 0ustar ripleyuserscontext("trafo") test_that("trafoValue with param", { p = makeNumericParam(id = "x", lower = -10, upper = 10, trafo = function(x) x^2) expect_equal(trafoValue(p, 1), 1) expect_equal(trafoValue(p, -5), 25) }) test_that("trafoValue with param set", { ps = makeParamSet( makeIntegerParam("u", trafo = function(x) 2 * x), makeNumericVectorParam("v", len = 2, trafo = function(x) x / sum(x)), makeDiscreteParam("w", values = c("a", "b"), trafo = function(x) paste0("=", x, "=")), makeDiscreteVectorParam("x", values = letters, len = 3, trafo = sort) ) expect_equal(trafoValue(ps, list(3, c(2, 4), "a", c("b", "a", "c"))), list(u = 6, v = c(2 / 6, 4 / 6), w = "=a=", x = c("a", "b", "c"))) # check if error is thrown when list has different names expect_error(trafoValue(ps, list(a = 1, b = 1, c = "b", d = c("a", "b", "c")))) # check if trafo function is applied on correct list-slots expect_equal(trafoValue(ps, list(w = "b", v = 1:2, u = 1, x = c("x", "f", "p"))), list(u = 2 * 1, v = 1:2 / sum(1:2), w = "=b=", x = c("f", "p", "x"))) }) test_that("trafo opt.path", { ps = makeParamSet( makeNumericParam("x", lower = -2, upper = 2, trafo = function(x) 2^x) ) op = makeOptPathDF(par.set = ps, y.names = "y", minimize = TRUE, add.transformed.x = FALSE) addOptPathEl(op, x = list(x = -2), y = 0) addOptPathEl(op, x = list(x = 2), y = 0) expect_error(addOptPathEl(op, x = list(x = 3), y = 0), "infeasible") op2 = trafoOptPath(op) df = as.data.frame(op2) expect_equal(df$x, c(1 / 4, 4)) expect_error(trafoOptPath(op2), "Cannot further trafo") ps = makeParamSet( makeIntegerParam("u", trafo = function(x) 2 * x), makeNumericVectorParam("v", len = 2, trafo = function(x) x / sum(x)), makeDiscreteParam("w", values = c("a", "b")) ) op = makeOptPathDF(ps, "y", TRUE) addOptPathEl(op, x = list(3, c(2, 4), "a"), y = 0, dob = 1, eol = 1) addOptPathEl(op, x = list(4, c(5, 3), "b"), y = 2, dob = 5, eol = 7) op2 = trafoOptPath(op) df2 = as.data.frame(op2) df2b = rbind( data.frame(u = 6, v1 = 2 / 6, v2 = 4 / 6, w = "a", y = 0, dob = 1, eol = 1, stringsAsFactors = TRUE), data.frame(u = 8, v1 = 5 / 8, v2 = 3 / 8, w = "b", y = 2, dob = 5, eol = 7, stringsAsFactors = TRUE) ) expect_equal(df2, df2b) }) test_that("trafo opt.path does not drop errmsg, exectime or extras", { ps = makeParamSet( makeNumericParam("x", lower = -2, upper = 2, trafo = function(x) 2^x) ) op = makeOptPathDF(par.set = ps, y.names = "y", minimize = TRUE, add.transformed.x = FALSE, include.error.message = TRUE, include.exec.time = TRUE, include.extra = TRUE) addOptPathEl(op, x = list(x = -2), y = 0, error.message = "foo", exec.time = 10, extra = list(e = 33, .f = iris)) op2 = trafoOptPath(op) df = as.data.frame(op2, include.rest = TRUE) expect_equal(df, data.frame(x = 1 / 4, y = 0, dob = 1, eol = NA_real_, error.message = "foo", exec.time = 10, e = 33, stringsAsFactors = FALSE)) el = getOptPathEl(op2, 1L) expect_equal(el$extra$.f, iris) }) ParamHelpers/tests/testthat/test_hasRequires.R0000644000176000001440000000060113633666270021355 0ustar ripleyuserscontext("hasRequires") test_that("hasRequires", { ps = makeParamSet() expect_false(hasRequires(ps)) ps = makeParamSet( makeNumericParam("x", lower = 1, upper = 2) ) expect_false(hasRequires(ps)) ps = makeParamSet( makeDiscreteParam("x", values = 1:2), makeNumericParam("y", lower = 1, upper = 2, requires = quote(x == 1)) ) expect_true(hasRequires(ps)) }) ParamHelpers/tests/testthat/test_filterParams.R0000644000176000001440000001003113633666270021511 0ustar ripleyuserscontext("FilterParams") test_that("filter empty paramset", { ps = makeParamSet() expect_true(isEmpty(filterParams(ps, type = "numeric"))) expect_true(isEmpty(filterParams(ps, type = "integer"))) expect_true(isEmpty(filterParams(ps, type = "numericvector"))) expect_true(isEmpty(filterParams(ps, type = "integervector"))) expect_true(isEmpty(filterParams(ps, type = "discrete"))) expect_true(isEmpty(filterParams(ps, type = "discretevector"))) expect_true(isEmpty(filterParams(ps, type = "logical"))) expect_true(isEmpty(filterParams(ps, type = "logicalvector"))) expect_true(isEmpty(filterParams(ps, type = "character"))) expect_true(isEmpty(filterParams(ps, type = "character"))) expect_true(isEmpty(filterParams(ps, type = "function"))) expect_true(isEmpty(filterParams(ps, type = "untyped"))) }) test_that("filter mixed paramset", { ps = makeParamSet( makeNumericParam("u", lower = 1), makeIntegerParam("v", lower = 1, upper = 2), makeDiscreteParam("w", values = 1:2), makeLogicalParam("x"), makeDiscreteVectorParam("y", len = 2, values = c("a", "b")), makeLogicalVectorParam("z", len = 3), makeCharacterVectorParam("s", len = 2) ) expect_equal(getParamIds(filterParams(ps, type = "numeric")), "u") expect_equal(getParamIds(filterParams(ps, type = "integer")), "v") expect_equal(getParamIds(filterParams(ps, type = "discrete")), "w") expect_equal(getParamIds(filterParams(ps, type = "logical")), "x") expect_equal(getParamIds(filterParams(ps, type = c("logical", "logicalvector"))), c("x", "z")) expect_equal(getParamIds(filterParams(ps, type = c("character", "charactervector"))), "s") expect_equal(getParamIds(filterParams(ps, type = "discretevector")), "y") expect_equal(getParamIds(filterParams(ps, type = c("numeric", "integer"))), c("u", "v")) expect_equal(getParamIds(filterParams(ps, type = c("integer", "numeric"))), c("u", "v")) expect_equal(getParamIds(filterParams(ps, type = c("integer", "function"))), "v") expect_true(isEmpty(filterParams(ps, type = "function"))) }) test_that("mix filtering of type and tunable", { ps = makeParamSet( makeNumericParam("u", lower = 1), makeNumericParam("v", lower = 1, tunable = FALSE), makeDiscreteParam("w", values = 1:2), makeIntegerParam("x", lower = 1, upper = 2), makeLogicalVectorParam("y", len = 3), makeUntypedParam("z") ) expect_equal(getParamIds(filterParams(ps, type = "numeric")), c("u", "v")) expect_equal(getParamIds(filterParams(ps, type = NULL)), c("u", "v", "w", "x", "y", "z")) expect_equal(getParamIds(filterParams(ps, type = c("numeric", "integer"), tunable = TRUE)), c("u", "x")) expect_equal(getParamIds(filterParams(ps, type = NULL, tunable = FALSE)), c("v")) expect_error(getParamIds(filterParams(ps, type = NULL, tunable = c(FALSE, FALSE)))) expect_error(getParamIds(filterParams(ps, type = NULL, tunable = NULL))) }) test_that("filtering of ids", { ps = makeParamSet( makeNumericParam("u", lower = 1), makeNumericParam("v", lower = 1, tunable = FALSE), makeDiscreteParam("w", values = 1:2), makeIntegerParam("x", lower = 1, upper = 2), makeLogicalVectorParam("y", len = 3), makeCharacterParam("s"), makeUntypedParam("z") ) expect_error(filterParams(ps, type = "numeric", ids = c("a", "u"))) expect_equal(getParamIds(filterParams(ps, type = "numeric", ids = c("v", "w", "y"))), "v") expect_equal(getParamIds(filterParams(ps, type = "character", ids = c("u", "v", "w", "s"))), "s") expect_equal(getParamIds(filterParams(ps, type = NULL, ids = c("v", "w", "y"))), c("v", "w", "y")) expect_equal(getParamIds(filterParams(ps, type = c("numeric", "integer"), tunable = TRUE, ids = c("w", "x", "y"))), "x") expect_true(isEmpty(filterParams(ps, type = "logical", ids = c("u", "v")))) }) test_that("filtering with requirements", { ps = makeParamSet( makeDiscreteParam("x", values = c("a", "b"), default = "a"), makeNumericParam("y", requires = quote(x == "a")) ) expect_error(filterParams(par.set = ps, type = "numeric", check.requires = TRUE), "Params x filtered") }) ParamHelpers/tests/testthat/helper_zzz.R0000644000176000001440000000001413164130622020177 0ustar ripleyusersset.seed(1) ParamHelpers/tests/run-all.R0000644000176000001440000000012413164130622015517 0ustar ripleyuserslibrary(testthat) library(BBmisc) library(ParamHelpers) test_check("ParamHelpers") ParamHelpers/src/0000755000176000001440000000000013636350403013457 5ustar ripleyusersParamHelpers/src/init.c0000644000176000001440000000105013633666270014573 0ustar ripleyusers#include #include #include // for NULL #include /* .Call calls */ extern SEXP c_dfRowsToList(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP c_trafo_and_set_dep_to_na(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); static const R_CallMethodDef CallEntries[] = { {"c_dfRowsToList", (DL_FUNC) &c_dfRowsToList, 6}, {NULL, NULL, 0} }; void R_init_ParamHelpers(DllInfo *dll) { R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); R_useDynamicSymbols(dll, FALSE); } ParamHelpers/src/c_dfRowsToList.c0000644000176000001440000000756013437170243016541 0ustar ripleyusers#include #include #include SEXP c_dfRowsToList(SEXP s_df, SEXP s_pars, SEXP s_types, SEXP s_parnames, SEXP s_lens, SEXP s_cnames) { int *types = INTEGER(s_types); int npars = LENGTH(s_lens); int *lens = INTEGER(s_lens); int nrow_df = LENGTH(VECTOR_ELT(s_df, 0)); int row, par, k; /* loop counters for rows, cols, params, vector param elements */ int type; /* type of column we are currently handling */ int parlen; /* length of param we are currently handling */ int colcount = 0; /* when we iterate params, what is the (first) column of s_df that corresponds? */ SEXP s_res, s_rowlist, s_parval; Rboolean all_missing; /* we iterate thru rows then params. */ s_res = PROTECT(NEW_LIST(nrow_df)); for (row = 0; row < nrow_df; row++) { s_rowlist = PROTECT(NEW_LIST(npars)); /* convert row to R objects and define them in envir s_env */ colcount = 0; for (par = 0; par < npars; par++) { /* iter thru params */ parlen = lens[par]; type = types[colcount]; all_missing = TRUE; /* copy vector-param block of row to s_parval */ if (type == 1) { /* numerics */ s_parval = PROTECT(NEW_NUMERIC(parlen)); for (k = 0; k < parlen; k++) { REAL(s_parval)[k] = REAL(VECTOR_ELT(s_df, colcount+k))[row]; if (!ISNAN(REAL(s_parval)[k])) all_missing = FALSE; } } else if (type == 2) { /* integers */ s_parval = PROTECT(NEW_INTEGER(parlen)); for (k = 0; k < parlen; k++) { INTEGER(s_parval)[k] = INTEGER(VECTOR_ELT(s_df, colcount+k))[row]; if (INTEGER(s_parval)[k] != NA_INTEGER) all_missing = FALSE; } } else if (type == 3) { /* factors */ s_parval = PROTECT(NEW_CHARACTER(parlen)); for (k = 0; k < parlen; k++) { SET_STRING_ELT(s_parval, k, STRING_ELT(VECTOR_ELT(s_df, colcount+k), row)); if (STRING_ELT(s_parval, k) != NA_STRING) all_missing = FALSE; } } else if (type == 4) { /* logical */ s_parval = PROTECT(NEW_LOGICAL(parlen)); for (k = 0; k < parlen; k++) { LOGICAL(s_parval)[k] = LOGICAL(VECTOR_ELT(s_df, colcount+k))[row]; if (LOGICAL(s_parval)[k] != NA_LOGICAL) all_missing = FALSE; } } else if (type == 5) { /* character */ s_parval = PROTECT(NEW_CHARACTER(parlen)); for (k = 0; k < parlen; k++) { SET_STRING_ELT(s_parval, k, STRING_ELT(VECTOR_ELT(s_df, colcount+k), row)); if (STRING_ELT(s_parval, k) != NA_STRING) all_missing = FALSE; } } else { error("should not happen!"); } /* are all entries in s_parval NA ? */ if (all_missing) s_parval = PROTECT(ScalarLogical(NA_LOGICAL)); /* convert discrete names to values */ if (!all_missing && type == 3) { SEXP pkg = PROTECT(ScalarString(mkChar("ParamHelpers"))); SEXP get_namespace = PROTECT(install("getNamespace")); SEXP fn = PROTECT(fn = lang2(get_namespace, pkg)); SEXP ns = PROTECT(ns = eval(fn, R_GlobalEnv)); SEXP s_call = PROTECT(lang3(install("discreteNameToValue"), R_NilValue, R_NilValue)); SETCADR(s_call, VECTOR_ELT(s_pars, par)); SETCADDR(s_call, s_parval); s_parval = PROTECT(eval(s_call, ns)); UNPROTECT(6); /* ns, s_call, ? */ } /* only support for cnames for num, int, log and char vecs currently */ if (type == 1 || type == 2 || type == 4 || type == 5) SET_NAMES(s_parval, VECTOR_ELT(s_cnames, par)); SET_VECTOR_ELT(s_rowlist, par, s_parval); SET_NAMES(s_rowlist, s_parnames); colcount += parlen; UNPROTECT(1); /* s_parval */ if (all_missing) UNPROTECT(1); } SET_VECTOR_ELT(s_res, row, s_rowlist); UNPROTECT(1); /* s_rowlist */ } UNPROTECT(1); /* s_res*/ return s_res; } ParamHelpers/R/0000755000176000001440000000000014260532101013060 5ustar ripleyusersParamHelpers/R/OptPathDF.R0000644000176000001440000000163113164130622015001 0ustar ripleyusers#' @rdname OptPath #' @aliases OptPathDF #' @export makeOptPathDF = function(par.set, y.names, minimize, add.transformed.x = FALSE, include.error.message = FALSE, include.exec.time = FALSE, include.extra = FALSE) { assertClass(par.set, "ParamSet") assertCharacter(y.names) assertLogical(minimize) assertFlag(add.transformed.x) assertFlag(include.error.message) assertFlag(include.exec.time) assertFlag(include.extra) n.y = length(y.names) obj = makeOptPath(par.set, y.names, minimize, add.transformed.x, include.error.message, include.exec.time, include.extra) obj$env$path = makeDataFrame(nrow = 0, ncol = getParamNr(par.set, devectorize = TRUE) + n.y, col.types = c(getParamTypes(par.set, df.cols = TRUE, df.discretes.as.factor = FALSE), rep("numeric", n.y)), col.names = c(getParamIds(par.set, repeated = TRUE, with.nr = TRUE), y.names) ) return(addClasses(obj, "OptPathDF")) } ParamHelpers/R/getParamLengths.R0000644000176000001440000000303713633666270016315 0ustar ripleyusers#' @title Return lengths of single parameters or parameters in parameter set. #' #' @description #' Useful for vector parameters. #' #' @template arg_par_or_set #' @template arg_dict #' @return (`integer`). Named and in the same order as the input for [ParamSet()] input. #' @examples #' ps = makeParamSet( #' makeNumericParam("u"), #' makeIntegerParam("v", lower = 1, upper = 2), #' makeDiscreteParam("w", values = 1:2), #' makeDiscreteVectorParam("x", len = 2, values = c("a", "b")) #' ) #' getParamLengths(ps) #' # the length of the vector x is 2, for all other single value parameters the length is 1. #' #' par = makeNumericVectorParam("x", len = expression(k), lower = 0) #' getParamLengths(par, dict = list(k = 4)) #' @export getParamLengths = function(par, dict = NULL) { UseMethod("getParamLengths") } #' @export getParamLengths.Param = function(par, dict = NULL) { assertClass(par, "Param") assertList(dict, names = "unique", null.ok = TRUE) if (length(par) == 0L) { return(integer(0L)) } length = par$len if (is.expression(length)) { length = eval(length, envir = dict) } as.integer(length) } #' @export getParamLengths.ParamSet = function(par, dict = NULL) { assertClass(par, "ParamSet") assertList(dict, names = "unique", null.ok = TRUE) if (isEmpty(par)) { return(integer(0L)) } lengths = extractSubList(par$pars, "len", simplify = FALSE) j = vlapply(par$pars, function(x) is.expression(x$len)) lengths[j] = lapply(lengths[j], eval, envir = dict) setNames(as.integer(lengths), names(lengths)) } ParamHelpers/R/getParamIds.R0000644000176000001440000000260213633666270015425 0ustar ripleyusers#' @title Return ids of parameters in parameter set. #' #' @description #' Useful if vectors are included. #' #' @template arg_par_or_set #' @param repeated (`logical(1)`)\cr #' Should ids be repeated length-times if parameter is a vector? #' Default is `FALSE`. #' @param with.nr (`logical(1)`)\cr #' Should number from 1 to length be appended to id if `repeated` is `TRUE`? #' Otherwise ignored. #' Default is `FALSE`. #' @return [`character`]. #' @export #' @examples #' ps = makeParamSet( #' makeNumericParam("u"), #' makeIntegerVectorParam("v", len = 2) #' ) #' getParamIds(ps) #' getParamIds(ps, repeated = TRUE) #' getParamIds(ps, repeated = TRUE, with.nr = TRUE) getParamIds = function(par, repeated = FALSE, with.nr = FALSE) { assertFlag(repeated) assertFlag(with.nr) UseMethod("getParamIds") } #' @export getParamIds.ParamSet = function(par, repeated = FALSE, with.nr = FALSE) { if (isEmpty(par)) { return(character(0L)) } unlist(lapply(par$pars, getParamIds, repeated = repeated, with.nr = with.nr), use.names = FALSE) } #' @export getParamIds.Param = function(par, repeated = FALSE, with.nr = FALSE) { pid = par$id if (repeated && isVector(par)) { n = par$len if (!is.na(n)) { if (n > 1L && with.nr) { paste(rep(pid, n), seq_len(n), sep = "") } else { rep(pid, n) } } else { pid } } else { pid } } ParamHelpers/R/getTypeStrings.R0000644000176000001440000000226013633666270016220 0ustar ripleyusers#' @title Get parameter type-strings. #' @description #' Returns type strings used in `param$type` for certain groups of parameters. #' @template arg_include_int #' @template arg_include_logical #' @return [`character`]. #' @name getTypeStrings #' @rdname getTypeStrings NULL #' @export #' @rdname getTypeStrings getTypeStringsAll = function() { ph$type.strings } #' @export #' @rdname getTypeStrings getTypeStringsNumeric = function(include.int = TRUE) { if (include.int) { ph$type.strings.numeric } else { ph$type.strings.double } } #' @export #' @rdname getTypeStrings getTypeStringsNumericStrict = function() { ph$type.strings.double } #' @export #' @rdname getTypeStrings getTypeStringsInteger = function() { ph$type.strings.integer } #' @export #' @rdname getTypeStrings getTypeStringsCharacter = function() { ph$type.strings.character } #' @export #' @rdname getTypeStrings getTypeStringsDiscrete = function(include.logical = TRUE) { if (include.logical) { c(ph$type.strings.discrete, ph$type.strings.logical) } else { ph$type.strings.discrete } } #' @export #' @rdname getTypeStrings getTypeStringsLogical = function() { ph$type.strings.logical } ParamHelpers/R/convertParamSetToIrace.R0000644000176000001440000000550313633666270017614 0ustar ripleyusers#' @title Converts a ParamSet object to a parameter object of the irace package. #' #' @description Converts to a textual description used in irace and then #' potentially calls [readParameters][irace::readParameters]. #' #' @template arg_parset #' @param as.chars (`logical(1)`)\cr Return results as character vector of lines #' `FALSE` or call [irace::readParameters()] on it (`TRUE`). Default is #' `FALSE`. #' @return [[list()]]. #' @export convertParamSetToIrace = function(par.set, as.chars = FALSE) { assertClass(par.set, "ParamSet") assertFlag(as.chars) if (!is.null(par.set$forbidden)) { stopf("Operation not allowed for param set with forbidden region currently!") } if (!hasFiniteBoxConstraints(par.set)) { stop("convertParamSetToIrace requires finite box constraints for all numeric and integer params!") } requirePackages("irace", why = "convertParamSetToIrace", default.method = "load") lines = character(0L) count = 1L for (i in seq_along(par.set$pars)) { p = par.set$pars[[i]] ptype = p$type type = switch( ptype, numeric = "r", numericvector = "r", integer = "i", integervector = "i", discrete = "c", discretevector = "c", logical = "c", logicalvector = "c", ordered = "o" ) for (j in seq_len(p$len)) { id = if (p$len == 1L) p$id else paste(p$id, j, sep = "") if (isNumericTypeString(ptype, include.int = FALSE)) { line = sprintf('%s "" %s (%g, %g)', id, type, p$lower[j], p$upper[j]) } else if (isIntegerTypeString(ptype)) { line = sprintf('%s "" %s (%i, %i)', id, type, p$lower[j], p$upper[j]) } else if (isDiscreteTypeString(ptype, include.logical = TRUE)) { v = paste("\"", names(p$values), "\"", sep = "") line = sprintf('%s "" %s (%s)', id, type, collapse(v)) } else { stopf("Unknown parameter type: %s", p$type) } if (hasRequires(p)) { line = paste(line, collapse(deparse(p$requires, width.cutoff = 500L), sep = ""), sep = " | ") } lines[count] = line count = count + 1L } } if (as.chars) { return(lines) } else { lines = collapse(lines, "\n") params = irace::readParameters(text = lines, digits = .Machine$integer.max) # fix numeric boundaries of irace, to make sure we dont lose num accuracy by write/read file IO # somehow bad.... for (p in par.set$pars) { if (isNumeric(p, include.int = TRUE)) { pids = getParamIds(p, repeated = TRUE, with.nr = TRUE) for (j in seq_len(p$len)) { if (isNumeric(p, include.int = FALSE)) { params$boundary[[pids[j]]] = c(p$lower[j], p$upper[j]) } if (isInteger(p)) { params$boundary[[pids[j]]] = as.integer(c(p$lower[j], p$upper[j])) } } } } return(params) } } ParamHelpers/R/OptPathDF_getter.R0000644000176000001440000000655413633666270016402 0ustar ripleyusers# return logical index for selection via dob and / or eol getOptPathDobAndEolIndex = function(op, dob = op$env$dob, eol = op$env$eol) { op$env$dob %in% dob & op$env$eol %in% eol } #' @export getOptPathLength.OptPathDF = function(op) { nrow(op$env$path) } #' @export getOptPathEl.OptPathDF = function(op, index) { index = asInt(index) n = getOptPathLength(op) if (!(index >= 1 && index <= n)) { stop("Index must be between 1 and ", n, "!") } e = op$env path = e$path y = unlist(path[index, op$y.names, drop = FALSE]) # remove y names from path, only consider x path = path[, setdiff(colnames(path), op$y.names), drop = FALSE] x = dfRowToList(path, op$par.set, index) res = list(x = x, y = y, dob = e$dob[index], eol = e$eol[index]) # if errmsg there, return it if (!is.null(e$error.message)) { res$error.message = e$error.message[index] } if (!is.null(e$exec.time)) { res$exec.time = e$exec.time[index] } if (!is.null(e$extra)) { res$extra = e$extra[[index]] } return(res) } #' @export getOptPathX.OptPathDF = function(op, dob = op$env$dob, eol = op$env$eol) { return(as.data.frame(op, include.x = TRUE, include.y = FALSE, include.rest = FALSE, dob = dob, eol = eol)) } #' @export getOptPathY.OptPathDF = function(op, names, dob = op$env$dob, eol = op$env$eol, drop = TRUE) { if (missing(names)) { names = op$y.names } else { c(names, subset = op$y.names) } assertFlag(drop) y = as.matrix(op$env$path[getOptPathDobAndEolIndex(op, dob, eol), names, drop = FALSE]) if (drop && length(names) == 1L) { y = as.numeric(y) } return(y) } #' @export getOptPathDOB.OptPathDF = function(op, dob = op$env$dob, eol = op$env$eol) { return(op$env$dob[getOptPathDobAndEolIndex(op, dob, eol)]) } #' @export getOptPathEOL.OptPathDF = function(op, dob = op$env$dob, eol = op$env$eol) { return(op$env$eol[getOptPathDobAndEolIndex(op, dob, eol)]) } #' @export getOptPathErrorMessages.OptPathDF = function(op, dob = op$env$dob, eol = op$env$eol) { return(op$env$error.message[getOptPathDobAndEolIndex(op, dob, eol)]) } #' @export getOptPathExecTimes.OptPathDF = function(op, dob = op$env$dob, eol = op$env$eol) { return(op$env$exec.time[getOptPathDobAndEolIndex(op, dob, eol)]) } #' @export getOptPathCol.OptPathDF = function(op, name, dob = op$env$dob, eol = op$env$eol) { assertString(name) if (getOptPathLength(op) == 0L) { stopf("Trying to return a col from an empty opt.path") } if (name %in% colnames(op$env$path)) { return(op$env$path[getOptPathDobAndEolIndex(op, dob, eol), name]) } if (name == "dob") { return(getOptPathDOB(op, dob, eol)) } if (name == "eol") { return(getOptPathEOL(op, dob, eol)) } if (name == "exec.time") { return(getOptPathExecTimes(op, dob, eol)) } if (name == "error.message") { return(getOptPathErrorMessages(op, dob, eol)) } if (name %in% names(op$env$extra[[1]]) || substr(name, 1, 1) == ".") { return(extractSubList(op$env$extra[getOptPathDobAndEolIndex(op, dob, eol)], name, simplify = substr(name, 1, 1) != ".")) } stop("The column you specified is not present in the opt.path.") } #' @export getOptPathCols.OptPathDF = function(op, names, dob = op$env$dob, eol = op$env$eol, row.names = NULL) { assertCharacter(names, any.missing = FALSE) d = as.data.frame(op, dob = dob, eol = eol, row.names = row.names) return(d[, names, drop = FALSE]) } ParamHelpers/R/isRequiresOk.R0000644000176000001440000000341113633666270015651 0ustar ripleyusers#' @title Check if parameter requirements are met. #' #' @description #' Check if a parameter value satisfies the requirements of the #' parameter description. This only checks the `requires` expressions. #' #' @template arg_parset #' @param par.vals (`list()`) \cr #' List of parameter settings. #' @param ids (`character()`) \cr #' `id`s of the param.vals to check. Default is `names(par.vals)`. #' @param use.defaults (`logical()`) \cr #' Some requirements relay on default values of the `par.set`. Default is #' `TRUE`, which means that if the value is not present in `par.vals` the #' default value will be considered. #' @return `logical(1)` \cr #' @export isRequiresOk = function(par.set, par.vals, ids = names(par.vals), use.defaults = TRUE) { assertClass(par.set, "ParamSet") assertList(par.vals, names = "named") if (is.numeric(ids)) { assertInteger(ids, lower = 1L, upper = length(par.vals), unique = TRUE) } else { assertSubset(ids, choices = names(par.vals)) } assertFlag(use.defaults) if (use.defaults) { par.vals.env = insert(getDefaults(par.set), par.vals) } else { par.vals.env = par.vals } requireOks = vlapply(names(par.vals), function(par.name) { requiresOk(par.set$pars[[par.name]], par.vals.env) }) if (any(!requireOks)) { # just constructing an informative error message # FIXME Maybe use paramValueToString par.names.failed = names(requireOks)[!requireOks] par.vals.failed = par.vals[par.names.failed] requires.failed = as.character(extractSubList(par.set$pars, "requires")[par.names.failed]) stopf("The following parameter settings do not meet the requirements: %s", paste0(par.names.failed, "=", par.vals.failed, " needs ", requires.failed, collapse = ", ")) } return(all(requireOks)) } ParamHelpers/R/isFeasible.R0000644000176000001440000001510013633666270015270 0ustar ripleyusers#' @title Check if parameter value is valid. #' #' @description Check if a parameter value satisfies the constraints of the #' parameter description. This includes the `requires` expressions and the #' `forbidden` expression, if `par` is a [ParamSet()]. If `requires` is not #' satisfied, the parameter value must be set to scalar `NA` to be still #' feasible, a single scalar even in a case of a vector parameter. If the result #' is `FALSE` the attribute `"warning"` is attached which gives the reason for #' the negative result. #' #' If the parameter has `cnames`, these are also checked. #' #' @template arg_par_or_set #' @param x (any) \cr #' Single value to check against the `Param` or `ParamSet`. For a `ParamSet` #' `x` must be a list. `x` has to contain the untransformed values. If the #' list is named, it is possible to only pass a subset of parameters defined #' in the [ParamSet()] `par`. In that case, only conditions regarding the #' passed parameters are checked. (Note that this might not work if one of the #' passed params has a `requires` setting which refers to an unpassed param.) #' @param use.defaults (`logical(1)`)\cr #' Whether defaults of the [Param()]/[ParamSet()] should be used if no values #' are supplied. If the defaults have requirements that are not met by `x` it #' will be feasible nonetheless. Default is `FALSE`. #' @param filter (`logical(1)`)\cr #' Whether the [ParamSet()] should be reduced to the space of the given Param #' Values. Note that in case of `use.defaults = TRUE` the filtering will be #' conducted after the insertion of the default values. Default is `FALSE`. #' @return `logical(1)`. #' @examples #' p = makeNumericParam("x", lower = -1, upper = 1) #' isFeasible(p, 0) # True #' isFeasible(p, 2) # False, out of bounds #' isFeasible(p, "a") # False, wrong type #' # now for parameter sets #' ps = makeParamSet( #' makeNumericParam("x", lower = -1, upper = 1), #' makeDiscreteParam("y", values = c("a", "b")) #' ) #' isFeasible(ps, list(0, "a")) # True #' isFeasible(ps, list("a", 0)) # False, wrong order #' @export isFeasible = function(par, x, use.defaults = FALSE, filter = FALSE) { UseMethod("isFeasible") } #' @export isFeasible.Param = function(par, x, use.defaults = FALSE, filter = FALSE) { # we don't have to consider requires here, it is not a param set constraintsOkParam(par, x) } #' @export isFeasible.LearnerParam = function(par, x, use.defaults = FALSE, filter = FALSE) { # we don't have to consider requires here, it is not a param set constraintsOkParam(par, x) } #' @export isFeasible.ParamSet = function(par, x, use.defaults = FALSE, filter = FALSE) { named = testNamed(x) assertList(x) res = FALSE # insert defaults if they comply with the requirements if (named && use.defaults) { x = updateParVals(old.par.vals = getDefaults(par), new.par.vals = x, par.set = par) } if (!named && filter) { stopf("filter = TRUE only works with named input") } if (named && any(names(x) %nin% getParamIds(par))) { stopf("Following names of given values do not match with ParamSet: %s", collapse(setdiff(names(x), getParamIds(par)))) } if (isForbidden(par, x)) { attr(res, "warning") = "The given parameter setting has forbidden values." return(res) } if (filter) { par = filterParams(par, ids = names(x)) x = x[getParamIds(par)] } else if (length(x) != length(par$pars)) { stopf("Param setting of length %i does not match ParamSet length %i", length(x), length(par$pars)) } if (!named) { names(x) = getParamIds(par) } missing.reqs = setdiff(getRequiredParamNames(par), names(x)) if (length(missing.reqs) > 0) { stopf("Following parameters are missing but needed for requirements: %s", collapse(missing.reqs)) } # FIXME: very slow for (i in seq_along(par$pars)) { p = par$pars[[i]] v = x[[i]] # no requires, just check constraints if (!requiresOk(p, x)) { # if not, val must be NA if (!isScalarNA(v)) { attr(res, "warning") = sprintf("Param %s is set but does not meet requirements %s", convertToShortString(x[i]), sQuote(collapse(deparse(p$requires), sep = ""))) return(res) } } else { # requires, ok, check constraints if (!isFeasible(p, v)) { attr(res, "warning") = sprintf("The parameter setting %s does not meet constraints", convertToShortString(x[i])) return(res) } } } return(TRUE) } # are the contraints ok for value of a param (not considering requires) constraintsOkParam = function(par, x) { if (isSpecialValue(par, x)) { return(TRUE) } type = par$type # this should work in any! case. if (type == "untyped") { return(TRUE) } inValues = function(v) any(vlapply(par$values, function(w) isTRUE(all.equal(w, v)))) ok = if (type == "numeric") { is.numeric(x) && length(x) == 1 && (par$allow.inf || is.finite(x)) && inBoundsOrExpr(par = par, x = x) } else if (type == "integer") { is.numeric(x) && length(x) == 1 && is.finite(x) && inBoundsOrExpr(par, x) && x == as.integer(x) } else if (type == "numericvector") { is.numeric(x) && checkLength(par, x) && all((par$allow.inf | is.finite(x)) & inBoundsOrExpr(par, x)) } else if (type == "integervector") { is.numeric(x) && checkLength(par, x) && all(is.finite(x) & inBoundsOrExpr(par, x) & x == as.integer(x)) } else if (type == "discrete") { inValues(x) } else if (type == "discretevector") { is.list(x) && checkLength(par, x) && all(vlapply(x, inValues)) } else if (type == "logical") { is.logical(x) && length(x) == 1 && !is.na(x) } else if (type == "logicalvector") { is.logical(x) && checkLength(par, x) && !anyMissing(x) } else if (type == "character") { is.character(x) && length(x) == 1 && !is.na(x) } else if (type == "charactervector") { is.character(x) && checkLength(par, x) && !anyMissing(x) } else if (type == "function") { is.function(x) } # if we have cnames, check them if (!is.null(par$cnames)) { ok = ok && !is.null(names(x)) && all(names(x) == par$cnames) } return(ok) } # checks if the requires part of the i-th param is valid for value x (x[[i]] is value or i-th param) requiresOk = function(par, x) { if (is.null(par$requires)) { TRUE } else { isTRUE(eval(par$requires, envir = x)) } } # helper function which checks whether 'x' lies within the boundaries (unless they are expressions) inBoundsOrExpr = function(par, x) { (is.expression(par$lower) || all(x >= par$lower)) && (is.expression(par$upper) || all(x <= par$upper)) } checkLength = function(par, x) { (is.expression(par$len) || is.na(par$len) || length(x) == par$len) } ParamHelpers/R/utils.R0000644000176000001440000000615113633666270014370 0ustar ripleyusersstopIfLearnerParams = function(par.set) { if (any(vlapply(par.set$pars, function(x) inherits(x, "LearnerParameter")))) { stop("No par.set parameter in 'generateDesign' can be of class 'LearnerParameter'! Use basic parameters instead to describe you region of interest!") } } stopIfFunOrUntypedParams = function(par.set) { types = getParamTypes(par.set) not.ok = intersect(c("untyped", "function", "character", "charactervector"), types) if (length(not.ok) > 0L) { stopf("Parameters of this type are not allowed, but were found: %s", collapse(not.ok)) } } doBasicGenDesignChecks = function(par.set) { assertClass(par.set, "ParamSet") if (isEmpty(par.set)) { stop("par.set must not be empty!") } stopIfLearnerParams(par.set) stopIfFunOrUntypedParams(par.set) lower = getLower(par.set, with.nr = TRUE) upper = getUpper(par.set, with.nr = TRUE) if (any(is.infinite(c(lower, upper)))) { stop("Finite box constraints required!") } return(list(lower = lower, upper = upper)) } getParamNA = function(par, repeated = FALSE) { v = switch(par$type, numeric = NA_real_, numericvector = NA_real_, integer = NA_integer_, integervector = NA_integer_, discrete = NA_character_, discretevector = NA_character_, logical = NA, logicalvector = NA, character = NA_character_, charactervector = NA_character_ ) if (repeated) { v = rep(v, par$len) } return(v) } # Create a list with the values from getValues, but respect vector parameters and # create a single list item for each vector component named paramId.number getParamSetValues = function(par.set) { pids1 = getParamIds(par.set, repeated = TRUE, with.nr = TRUE) pids2 = getParamIds(par.set, repeated = TRUE, with.nr = FALSE) values1 = getValues(par.set) values2 = lapply(pids2, function(x) { names(values1[[x]]) }) setNames(values2, pids1) } # Makes sure we keep all levels of a discrete vector and also keep them in order. fixDesignFactors = function(des, par.set) { types.df = getParamTypes(par.set, df.cols = TRUE) values = getParamSetValues(par.set) for (i in which(types.df == "factor")) { des[, i] = factor(des[, i], levels = values[[colnames(des)[i]]]) } des } # Ensure that the types of Design columns are always correct, # e.g., columns that are always NA or integer if default in integer par is numeric fixDesignVarTypes = function(des, par.set) { types = getParamTypes(par.set, use.names = TRUE, df.cols = TRUE) for (p in colnames(des)) { des[, p] = as(des[, p], types[p]) } des } # Convert Expressions to call (what we get from quote) convertExpressionToCall = function(req) { if (is.expression(req)) { if (length(req) == 1) { return(req[[1]]) } else { return(substitute(eval(x), list(x = req))) } } req } # adapted from mlr-org/mlr3misc/purrr_map.R map_dtc mapDfc = function(.x, .f, ...) { cols = lapply(.x, .f, ...) j = vapply(cols, function(x) !is.null(dim(x)) && !is.null(colnames(x)), FUN.VALUE = NA, USE.NAMES = FALSE) names(cols)[j] = "" do.call(data.frame, c(cols, list(check.names = TRUE, stringsAsFactors = FALSE))) } ParamHelpers/R/zzz.R0000644000176000001440000000207513633666270014066 0ustar ripleyusers#' @import checkmate #' @import methods #' @import stats #' @importFrom fastmatch %fin% fmatch #' @rawNamespace import(BBmisc, except = isFALSE) NULL .onLoad = function(libname, pkgname) { backports::import(pkgname) } ph = new.env(parent = emptyenv()) ph$type.strings.integer = c("integer", "integervector") ph$type.strings.double = c("numeric", "numericvector") ph$type.strings.character = c("character", "charactervector") ph$type.strings.logical = c("logical", "logicalvector") ph$type.strings.discrete = c("discrete", "discretevector") ph$type.strings.numeric = c(ph$type.strings.integer, ph$type.strings.double) ph$type.strings = c(ph$type.strings.integer, ph$type.strings.double, ph$type.strings.character, ph$type.strings.logical, ph$type.strings.discrete, "untyped", "function") ph$convert.param.types.from = c("numericvector", "integervector", "discrete", "discretevector", "logicalvector", "charactervector") ph$convert.to.ctypes = c("numeric", "integer", "factor", "logical", "character") ph$value.component.names = c("numericvector", "integervector", "logicalvector") ParamHelpers/R/convertDiscrete.R0000644000176000001440000000501313633666270016367 0ustar ripleyusers#' @title Convert encoding name(s) to discrete value(s). #' #' @description For a discrete parameter or discrete vector. If the `name` is #' `NA`, indicating a missing parameter value due to unsatisfied requirements, #' `NA` is returned. #' #' @template arg_par #' @param name (`character`)\cr #' Name (string) encoding the value for a discrete #' parameter, or a character vector of names for a discrete vector. #' @return [any]. Parameter value for a discrete parameter or a list of values #' for a discrete vector. #' @examples #' p = makeDiscreteParam("u", values = c(x1 = "a", x2 = "b", x3 = "b")) #' discreteNameToValue(p, "x3") #' @export discreteNameToValue = function(par, name) { # handle missing parameter values (requires) if (isScalarNA(name)) { return(NA) } assertClass(par, "Param") assertChoice(par$type, c("discrete", "discretevector")) assertCharacter(name, len = ifelse(par$type == "discrete", 1L, par$len)) d = setdiff(name, names(par$values)) if (length(d) > 0L) { stopf("Names not used in values for parameter %s: %s", par$id, collapse(d)) } if (par$type == "discrete") { par$values[[name]] } else if (par$type == "discretevector") { par$values[name] } } #' @title Convert discrete value(s) to encoding name(s). #' #' @description #' For a discrete parameter or discrete vector. #' If the value `x` is `NA`, indicating a missing parameter value due to unsatisfied requirements, #' `NA` is returned. #' #' @template arg_par #' @param x [any]\cr #' Parameter value or a list of values for a discrete vector. #' @return [`character`]. Single name for a discrete parameter or a character vector of #' names for a discrete vector. #' @examples #' p = makeDiscreteParam("u", values = c(x1 = "a", x2 = "b", x3 = "c")) #' discreteValueToName(p, "b") #' @export discreteValueToName = function(par, x) { # handle missing parameter values (requires) if (isScalarNA(x)) { return(NA_character_) } assertClass(par, "Param") assertChoice(par$type, c("discrete", "discretevector")) if (par$type == "discretevector" && length(x) != par$len) { stopf("Length of x must be %i!", par$len) } ns = names(par$values) getIndex = function(values, v) { j = which(vlapply(values, function(w) isTRUE(all.equal(w, v, tolerance = .Machine$double.eps)))) if (length(j) == 0) { stop("Value not found!") } return(j) } if (par$type == "discrete") { ns[getIndex(par$values, x)] } else if (par$type == "discretevector") { ns[sapply(x, getIndex, values = par$values)] } } ParamHelpers/R/generateGridDesign.R0000644000176000001440000001155613636347536016773 0ustar ripleyusers#' @title Generates a grid design for a parameter set. #' #' @description #' The following types of columns are created: #' \tabular{ll}{ #' numeric(vector) \tab `numeric` \cr #' integer(vector) \tab `integer` \cr #' discrete(vector) \tab `factor` (names of values = levels) \cr #' logical(vector) \tab `logical` #' } #' If you want to convert these, look at [BBmisc::convertDataFrameCols()]. #' Dependent parameters whose constraints are unsatisfied generate `NA` entries #' in their respective columns. For discrete vectors the levels and their order #' will be preserved. #' #' The algorithm currently performs these steps: #' \enumerate{ #' \item{We create a grid. For numerics and integers we use the specified resolution. For discretes all values will be taken.} #' \item{Forbidden points are removed.} #' \item{Parameters are trafoed (potentially, depending on the setting of argument `trafo`); #' dependent parameters whose constraints are unsatisfied are set to `NA` entries.} #' \item{Duplicated points are removed. Duplicated points are not generated in a #' grid design, but the way parameter dependencies are handled make this possible.} #' } #' #' Note that if you have trafos attached to your params, the complete creation #' of the design (except for the detection of invalid parameters w.r.t to their #' `requires` setting) takes place on the UNTRANSFORMED scale. So this function #' creates a regular grid over the param space on the UNTRANSFORMED scale, but #' not necessarily the transformed scale. #' #' `generateDesign` will NOT work if there are dependencies over multiple levels #' of parameters and the dependency is only given with respect to the #' \dQuote{previous} parameter. A current workaround is to state all #' dependencies on all parameters involved. (We are working on it.) #' #' @template arg_parset #' @param resolution (`integer`)\cr #' Resolution of the grid for each numeric/integer parameter in `par.set`. #' For vector parameters, it is the resolution per dimension. #' Either pass one resolution for all parameters, or a named vector. #' @template arg_trafo #' @template ret_gendes_df #' @export #' @examples #' ps = makeParamSet( #' makeNumericParam("x1", lower = -2, upper = 1), #' makeNumericParam("x2", lower = -2, upper = 2, trafo = function(x) x^2) #' ) #' generateGridDesign(ps, resolution = c(x1 = 4, x2 = 5), trafo = TRUE) generateGridDesign = function(par.set, resolution, trafo = FALSE) { doBasicGenDesignChecks(par.set) pars = par.set$pars n = length(pars) lens = getParamLengths(par.set) m = sum(lens) pids = getParamIds(par.set, repeated = TRUE, with.nr = TRUE) par.set.num = filterParamsNumeric(par.set, include.int = TRUE) pids.num = getParamIds(par.set.num) if (hasNumeric(par.set, include.int = TRUE)) { if (isScalarNumeric(resolution)) { resolution = setNames(rep(resolution, length(pids.num)), pids.num) } resolution = asInteger(resolution, lower = 1L, len = length(pids.num), names = "named") if (!all(names(resolution) %in% pids.num)) { stop("'resolution' must be named with parameter ids!") } } assertFlag(trafo) vals.list = setNames(vector("list", m), pids) el.counter = 1L # iterate over all params and discretize them for (i in seq_len(n)) { p = pars[[i]] if (isNumeric(p)) { lower = p$lower upper = p$upper } if (isDiscrete(p, include.logical = FALSE)) { discvals = p$values } # iterate over vector elements and d for (j in seq_len(p$len)) { if (isDiscrete(p, include.logical = FALSE)) { newvals = names(discvals) } else if (isLogical(p)) { newvals = c(TRUE, FALSE) } else if (isNumeric(p, include.int = TRUE)) { newvals = seq(from = lower[[j]], to = upper[[j]], length.out = resolution[[p$id]]) # round for integer if (isInteger(p)) { newvals = as.integer(unique(round(newvals))) } } else { stopf("generateGridDesign cannot be used for param '%s' of type '%s'!", p$id, p$type) } vals.list[[el.counter]] = newvals el.counter = el.counter + 1 } } res = expand.grid(vals.list, KEEP.OUT.ATTRS = FALSE, stringsAsFactors = FALSE) # data types here: # num(vec): numeric # int(vec): integer # log(vec): logical # dis(vec): character colnames(res) = pids # check each row if forbidden, then remove if (hasForbidden(par.set)) { # FIXME: this is pretty slow, but correct fb = rowSapply(res, isForbidden, par.set = par.set) res = res[!fb, , drop = FALSE] } if (trafo) { res = applyTrafos(res, pars) } if (hasRequires(par.set)) { res = setRequiresToNA(res, pars) } # remove duplicates res = res[!duplicated(res), , drop = FALSE] res = convertDataFrameCols(res, chars.as.factor = TRUE) # fix factors res = fixDesignFactors(res, par.set) attr(res, "trafo") = trafo return(res) } ParamHelpers/R/OptPath_setter.R0000644000176000001440000000625313633666270016200 0ustar ripleyusers#' Set the dates of birth of parameter values, in-place. #' #' @template arg_op #' @param index [integer]\cr #' Vector of indices of elements. #' @param dob [integer] \cr #' Dates of birth, single value or same length of `index`. #' @return Nothing. #' @export #' @family optpath setOptPathElDOB = function(op, index, dob) { assertClass(op, "OptPath") index = asInteger(index) dob = asInteger(dob) op$env$dob[index] = dob return(invisible(NULL)) } #' Set the end of life dates of parameter values, in-place. #' #' @template arg_op #' @param index [integer]\cr #' Vector of indices of elements. #' @param eol [integer] \cr #' EOL dates, single value or same length of `index`. #' @return Nothing. #' @export #' @family optpath setOptPathElEOL = function(op, index, eol) { assertClass(op, "OptPath") index = asInteger(index) eol = asInteger(eol) op$env$eol[index] = eol return(invisible(NULL)) } #' @title Add a new element to an optimization path. #' #' @description #' Changes the argument in-place. Note that when adding parameters that have #' associated transformations, it is probably best to add the untransformed #' values to the path. Otherwise you have to switch off the feasibility check, #' as constraints might now not hold anymore. #' #' Dependent parameters whose requirements are not satisfied must be represented #' by a scalar NA in the input. #' #' @template arg_op #' @param x (`list`)\cr #' List of parameter values for a point in input space. Must be in same order #' as parameters. #' @param y (`numeric`)\cr #' Vector of fitness values. Must be in same order as `y.names`. #' @param dob (`integer(1)`)\cr #' Date of birth of the new parameters. #' Default is length of path + 1. #' @param eol (`integer(1)`)\cr #' End of life of point. #' Default is `NA`. #' @param error.message (`character(1)`)\cr #' Possible error message that occurred for this parameter values. #' Default is `NA`. #' @param exec.time (`numeric(1)`)\cr #' Possible exec time for this evaluation. #' Default is `NA`. #' @param extra (`list`)\cr #' Possible list of extra values to store. #' The list must be fully named. The list can contain nonscalar values, but #' these nonscalar entries must have a name starting with a dot (`.`). #' Other entries must be scalar, and must be in the same order of all calls of #' `addOptPathEl`. #' Watch out: if `include.extra` was set to `TRUE` in (makeOptPathDF()) #' the list of extras is mandatory. #' Default is `NULL`. #' @param check.feasible (`logical(1)`)\cr #' Should `x` be checked with (isFeasible())? #' Default is `TRUE`. #' @return Nothing. #' @export #' @family optpath #' @examples #' ps = makeParamSet( #' makeNumericParam("p1"), #' makeDiscreteParam("p2", values = c("a", "b")) #' ) #' op = makeOptPathDF(par.set = ps, y.names = "y", minimize = TRUE) #' addOptPathEl(op, x = list(p1 = 7, p2 = "b"), y = 1) #' addOptPathEl(op, x = list(p1 = -1, p2 = "a"), y = 2) #' as.data.frame(op) addOptPathEl = function(op, x, y, dob = getOptPathLength(op) + 1L, eol = as.integer(NA), error.message = NA_character_, exec.time = NA_real_, extra = NULL, check.feasible = !op$add.transformed.x) { UseMethod("addOptPathEl") } ParamHelpers/R/OptPath_plotYTraces.R0000644000176000001440000000651713636346430017142 0ustar ripleyusers#' @title Plots Y traces of multiple optimization paths #' #' @description Can be used for only single-objective optimization paths. Useful #' to compare runs of different algorithms on the same optimization problem. You #' can add your own ggplot layers to the resulting plot object. #' #' @param opt.paths [[OptPath()] | list of [OptPath()]]\cr #' Object(s) to plot. #' @param over.time [`character`]\cr #' Should the traces be plotted versus the iteration number or the cumulated #' execution time? For the later, the opt.path has to contain a extra column #' names exec.time. Possible values are dob and exec.time, default is `dob`. #' @return ggplot2 plot object renderYTraces = function(opt.paths, over.time = "dob") { opt.paths = ensureVector(opt.paths, cl = "OptPath", n = 1L, names = "opt.path") assertList(opt.paths, types = "OptPath", min.len = 1L, names = "unique") assertChoice(over.time, choices = c("dob", "exec.time")) run.name = names(opt.paths) y.name = NULL minimize = NULL data = data.frame() # combine y traces for this algo + add algo / repl + do some sanity checks fronts = lapply(seq_along(opt.paths), function(j) { run = opt.paths[[j]] name = names(as.data.frame(run, include.x = FALSE, include.rest = FALSE, stringsAsFactors = TRUE)) if (j == 1L) { y.name <<- name minimize <<- run$minimize } if (length(name) != 1L) { stopf("Must always have 1 objective in opt path. But found: %i", length(name)) } if (!y.name == name) { stopf("Must always have the same objective in opt path: %s (first ones taken). But found here: %s", y.name, name) } if (!minimize == run$minimize) { stopf("Must always have the same 'minimize' settings for objective in opt path: %s (first one taken). But found here: %s", minimize, run$minimize) } if (over.time == "dob") { df = data.frame( y = getOptPathY(op = run), time = getOptPathDOB(op = run), stringsAsFactors = TRUE ) } if (over.time == "exec.time") { times = seq(0, sum(getOptPathExecTimes(run)), length.out = 128) df = getOptPathColAtTimes(run, times) df = df[, c(y.name, "time")] } # add column for algorithm and replication cbind(df, .algo = run.name[j], stringsAsFactors = TRUE) }) data = do.call(rbind, fronts) mean.data = aggregate(data[[y.name]], by = list(data$time, data$.algo), FUN = mean) names(mean.data) = c("time", ".algo", y.name) pl = ggplot2::ggplot(data, ggplot2::aes_string(x = "time", y = y.name, group = ".algo", linetype = ".algo", col = ".algo")) if (over.time == "dob") { pl = pl + ggplot2::geom_point(size = 3) } pl = pl + ggplot2::geom_line(data = mean.data, size = 1) return(pl) } #' @title Plots Y traces of multiple optimization paths #' #' @description Plot function for [renderYTraces()] #' #' @param opt.paths [`list`]\cr #' List of `OptPath` objects #' @param over.time [`character`]\cr #' Should the traces be plotted versus the iteration number or the cumulated #' execution time? For the later, the opt.path has to contain a extra column #' names exec.time. Possible values are dob and exec.time, default is `dob`. #' #' @return [`NULL`] #' #' @export plotYTraces = function(opt.paths, over.time = "dob") { print(renderYTraces(opt.paths, over.time)) return(invisible(NULL)) } ParamHelpers/R/evaluateParamExpressions.R0000644000176000001440000000536413633666270020267 0ustar ripleyusers#' @title Evaluates all expressions within a parameter. #' #' @description Evaluates the expressions of a parameter, parameter set or list #' of parameters for a given dictionary. #' #' @param obj ([Param()] | [ParamHelpers::ParamSet()] | `list`)\cr #' Parameter, parameter set or list of parameter values. Expressions within #' `len`, `lower` or `upper` boundaries, `default` or `values` will be #' evaluated using the provided dictionary (`dict`). #' @template arg_dict #' @return [[Param()] | [ParamHelpers::ParamSet()] | `list`]. #' @export #' @examples #' ps = makeParamSet( #' makeNumericParam("x", lower = expression(p), upper = expression(ceiling(3 * p))), #' makeIntegerParam("y", lower = 1, upper = 2) #' ) #' evaluateParamExpressions(ps, dict = list(p = 3)) #' #' ps = makeParamSet( #' makeNumericParam("x", default = expression(sum(data$Species == "setosa"))), #' makeIntegerParam("y", lower = 1, upper = 2), #' keys = c("data", "Species") #' ) #' evaluateParamExpressions(ps, dict = list(data = iris)) #' #' par.vals = list( #' x = expression(k), #' y = 5 #' ) #' evaluateParamExpressions(par.vals, dict = list(k = 3)) evaluateParamExpressions = function(obj, dict = NULL) { UseMethod("evaluateParamExpressions") } #' @export evaluateParamExpressions.Param = function(obj, dict = NULL) { assertClass(obj, "Param") if (!hasExpression(obj)) { return(obj) } assertList(dict, names = "unique", null.ok = TRUE) # replace expressions in length (needs to be done prior to computing # defaults, values and boundaries) length = getParamLengths(par = obj, dict = dict) obj$len = asInt(length, na.ok = TRUE) # replace expressions in default, values and boundaries if (!is.null(obj$lower)) { obj$lower = unname(getLower(obj = obj, dict = dict)) } if (!is.null(obj$upper)) { obj$upper = unname(getUpper(obj = obj, dict = dict)) } if (!is.null(obj$default)) { obj$default = getDefaults(obj = obj, dict = dict) } if (!is.null(obj$values)) { obj$values = getValues(obj = obj, dict = dict) } return(obj) } #' @export evaluateParamExpressions.ParamSet = function(obj, dict = NULL) { assertClass(obj, "ParamSet") if (!hasExpression(obj)) { return(obj) } assertList(dict, names = "unique", null.ok = TRUE) ids = names(obj$pars) # evaluate all parameters separately obj$pars = lapply(obj$pars, function(par) { evaluateParamExpressions(obj = par, dict = dict) }) names(obj$pars) = ids return(obj) } #' @export evaluateParamExpressions.list = function(obj, dict = NULL) { assertClass(obj, "list") assertList(dict, names = "unique", null.ok = TRUE) ids = names(obj) # evaluate all parameter values separately setNames(lapply(obj, function(par) { eval(expr = par, envir = dict) }), ids) } ParamHelpers/R/setValueCNames.R0000644000176000001440000000137613633666270016113 0ustar ripleyusers#' @title Set components names for vector names #' #' @description #' If param has `cnames` set component names in a value. #' Otherwise `x` is left unchanged. #' #' @template arg_par_or_set #' @param x (any) \cr #' Param value(s). #' For a parameter set this must be a list in the correct order. #' @return `x` with changed names. #' @export setValueCNames = function(par, x) { UseMethod("setValueCNames") } #' @export setValueCNames.Param = function(par, x) { # do not set names for missing / req.params if (par$type %fin% ph$value.component.names && !isScalarNA(x)) { names(x) = par$cnames } return(x) } #' @export setValueCNames.ParamSet = function(par, x) { assertList(x, len = length(par$pars)) Map(setValueCNames.Param, par$pars, x) } ParamHelpers/R/generateRandomDesign.R0000644000176000001440000000445213636346430017313 0ustar ripleyusers#' @title Generates a random design for a parameter set. #' #' @description #' The following types of columns are created: #' \tabular{ll}{ #' numeric(vector) \tab `numeric` \cr #' integer(vector) \tab `integer` \cr #' discrete(vector) \tab `factor` (names of values = levels) \cr #' logical(vector) \tab `logical` #' } #' If you want to convert these, look at [BBmisc::convertDataFrameCols()]. For #' discrete vectors the levels and their order will be preserved, even if not #' all levels are present. #' #' The algorithm simply calls [sampleValues()] and arranges the result in a #' data.frame. #' #' Parameters are trafoed (potentially, depending on the setting of argument #' `trafo`); dependent parameters whose constraints are unsatisfied are set to #' `NA` entries. #' #' `generateRandomDesign` will NOT work if there are dependencies over multiple #' levels of parameters and the dependency is only given with respect to the #' \dQuote{previous} parameter. A current workaround is to state all #' dependencies on all parameters involved. (We are working on it.) #' #' Note that if you have trafos attached to your params, the complete creation #' of the design (except for the detection of invalid parameters w.r.t to their #' `requires` setting) takes place on the UNTRANSFORMED scale. So this function #' samples from a uniform density over the param space on the UNTRANSFORMED #' scale, but not necessarily the transformed scale. #' #' @template arg_gendes_n #' @template arg_parset #' @template arg_trafo #' @template ret_gendes_df #' @export generateRandomDesign = function(n = 10L, par.set, trafo = FALSE) { doBasicGenDesignChecks(par.set) des = sampleValues(par.set, n, discrete.names = TRUE, trafo = trafo) # FIXME: all next lines are sloooow in R I guess. C? elementsToDf = function(x) { Map(function(p, v) { # blow up scalar NAs if (isScalarNA(v)) { v = as.data.frame(t(rep(v, p$len)), stringsAsFactors = TRUE) } else { as.data.frame(t(v), stringsAsFactors = TRUE) } }, par.set$pars, x) } des = lapply(des, elementsToDf) des = lapply(des, do.call, what = cbind) des = do.call(rbind, des) colnames(des) = getParamIds(par.set, repeated = TRUE, with.nr = TRUE) des = fixDesignFactors(des, par.set) attr(des, "trafo") = trafo return(des) } ParamHelpers/R/OptPathDF_setter.R0000644000176000001440000000622113633666270016405 0ustar ripleyusers#' @export addOptPathEl.OptPathDF = function(op, x, y, dob = getOptPathLength(op) + 1L, eol = NA_integer_, error.message = NA_character_, exec.time = NA_real_, extra = NULL, check.feasible = !op$add.transformed.x) { env = op$env assertList(x, len = length(op$par.set$pars)) assertNumeric(y, len = length(op$y.names)) eol = asInt(eol, na.ok = TRUE) dob = asInt(dob, na.ok = TRUE) assertString(error.message, na.ok = TRUE) assertNumber(exec.time, lower = 0, na.ok = TRUE) if (!is.null(env$extra) && (is.null(extra) || length(extra) == 0)) { stopf("You have to add extras to opt path if the option is enabled.") } if (!is.null(extra)) { if (is.null(env$extra)) { stopf("Trying to add extra info to opt path, without enabling that option!") } assertList(extra) if (!isProperlyNamed(extra)) { stopf("'extra' must be properly named!") } nondot.extra = removeDotEntries(extra) if (!all(vlapply(nondot.extra, isScalarValue))) { stopf("'nondot' components of 'extra' can only contain scalar values! use the 'dotted' components for more complex objects!") } if (length(env$extra) > 0L) { nondot.extra.precedent = removeDotEntries(env$extra[[1L]]) unknown.extra = setdiff(names(nondot.extra), names(nondot.extra.precedent)) missing.extra = setdiff(names(nondot.extra.precedent), names(nondot.extra)) if (length(unknown.extra) > 0) { stopf("Trying to add unknown extra(s): %s!", collapse(unknown.extra)) } if (length(missing.extra) > 0) { stopf("Trying to add extras but missing: %s!", collapse(missing.extra)) } } env$extra[[length(env$extra) + 1L]] = extra } if (!is.na(error.message) && is.null(env$error.message)) { stopf("Trying to add error.message to opt path, without enabling that option!") } if (!is.na(exec.time) && is.null(env$exec.time)) { stopf("Trying to add exec.time to opt path, without enabling that option!") } if (check.feasible) { if (!isFeasible(op$par.set, x)) { stop("Trying to add infeasible x values to opt path: ", convertToShortString(x)) } } # scalar_na -> single_NA, disc --> names, ints --> make sure int recode = function(ps, x) { Map(function(p, v) { if (isScalarNA(v)) { v = getParamNA(p, repeated = TRUE) } else if (p$type %fin% getTypeStringsDiscrete(FALSE)) { discreteValueToName(p, v) } # we need to make sure cols in df do not get converted to num else if (p$type %fin% getTypeStringsInteger()) { as.integer(v) } else { v } }, ps$pars, x) } # add x and y x = recode(op$par.set, x) el = do.call(cbind, lapply(x, function(v) as.data.frame(t(v), stringsAsFactors = FALSE))) el = cbind(el, as.data.frame(as.list(y), stringsAsFactors = FALSE)) colnames(el) = colnames(env$path) env$path = rbind(env$path, el) # add dob and eol k = length(env$dob) + 1 env$dob[k] = dob env$eol[k] = eol # potentially add errmsg and time if (!is.null(env$error.message)) { env$error.message[k] = error.message } if (!is.null(env$exec.time)) { env$exec.time[k] = exec.time } return(invisible(NULL)) } ParamHelpers/R/isForbidden.R0000644000176000001440000000102213633666270015450 0ustar ripleyusers#' @title Check whether parameter setting lies in forbidden region of parameter #' set. #' #' @description Parameter sets without a forbidden region always return `FALSE`. #' #' @template arg_parset #' @param x (named `list`) \cr #' Parameter setting to check. #' @return `logical(1)`. #' @export isForbidden = function(par.set, x) { assertClass(par.set, "ParamSet") # FIXME: check for correct names here assertList(x) if (!hasForbidden(par.set)) { return(FALSE) } return(eval(par.set$forbidden, envir = x)) } ParamHelpers/R/renderOptPathPlot_helpers.R0000644000176000001440000002445114260532061020356 0ustar ripleyusers# Check the given X and Y limit list. Each list can have 2 elements: # XSpace and YSpace. If the element is NULL, it is set, otherwise it is # checked. If the dimensionality of X and Y space is greater than 2, the limits # are set to NULL. The same happens if there is a discrete variable in the 2D case. # We don't need limits in this cases. # If the dimensionality is 1 for X or Y Space, for this space the ylim is NULL. getOptPathLims = function(xlim, ylim, op.x, op.y, iters, scale) { assertList(xlim) assertList(ylim) # First, we calculate for XSpace and YSpace plot the limits # Nasty ifs, since this can be one of half a dozen plots, and for every # plot we have different defaults for (space in c("XSpace", "YSpace")) { op.frame = if (space == "XSpace") op.x else op.y dim = ncol(op.frame) classes = BBmisc::vcapply(op.frame, function(x) class(x)) # For Multi-D Plot, no limits are needed. Warn, if the user specified some # and set to NULL if (dim > 2L) { if (!is.null(xlim[[space]])) { warning(paste("You specified xlims for multi-D plot in", space, "but xlims for this plots are not supported.")) } if (!is.null(ylim[[space]])) { warning("You specified ylims for multi-D plot in", space, "but ylims for this plots are not supported.") } xlim[[space]] = NULL ylim[[space]] = NULL next } # For 1Dnumeric this is easy - either check user input # or set to min - scale * range and max + scale * range if (dim == 1L && (classes == "numeric")) { if (is.null(xlim[[space]])) { xlim[[space]] = range(op.frame[, 1L]) xlim[[space]] = c(-1, 1) * scale * abs(diff(xlim[[space]])) + xlim[[space]] } else { assertNumeric(xlim[[space]], len = 2L, any.missing = FALSE) } if (!is.null(ylim[[space]])) { warning("You specified ylims for 1D numeric plot in", space, "but ylims for this plots are not supported.") } ylim[[space]] = NULL next } # limits for barplot (1D discrete case) # Here, xlims are not meaningful, ylim is the modal value if (dim == 1L && classes == "factor") { if (!is.null(xlim[[space]])) { warning(paste("You specified xlims for 1D barplot in", space, "but xlims for this plots are not supported.")) } xlim[[space]] = NULL if (is.null(ylim[[space]])) { ylim[[space]] = c(0, max(table(op.frame))) } else { assertNumeric(ylim[[space]], len = 2L, any.missing = FALSE) } next } # For dim = 2L we have to check for both variables, if they are discrete # for discrete, we don't want limits, for factors they are not meaningful if (dim == 2L) { if (classes[1L] == "numeric") { if (is.null(xlim[[space]])) { xlim[[space]] = range(op.frame[, 1L]) xlim[[space]] = c(-1, 1) * scale * abs(diff(xlim[[space]])) + xlim[[space]] } else { assertNumeric(xlim[[space]], len = 2L, any.missing = FALSE) } } else { if (!is.null(xlim[[space]])) { warning(paste("You specified xlims for 2D scatter plot in", space, "but the variable is discrete here and therefor xlims are not supported.")) } xlim[[space]] = NULL } if (classes[2L] == "numeric") { if (is.null(ylim[[space]])) { ylim[[space]] = range(op.frame[, 2L]) ylim[[space]] = c(-1, 1) * scale * abs(diff(ylim[[space]])) + ylim[[space]] } else { assertNumeric(ylim[[space]], len = 2L, any.missing = FALSE) } } else { if (!is.null(ylim[[space]])) { warning(paste("You specified ylims for 2D scatter plot in", space, "but the variable is discrete here and therefor ylims are not supported.")) } ylim[[space]] = NULL } } } # For now I say: The code for checking and limits for the over.time.plots # is way to bad and very complicated. It's not worth the afford atm, since in # 99% the defaults of ggplot are the way to go. # the user can get the plots via render, he has to set the limits here # for himself # NOTE: This code is not finished! # # Now we need the limits for over.time plots. This is a bit complicated, # # since we can have a list of over.time plots, so we also can get # # a list of lims. # for (space in c("x.over.time", "y.over.time")) { # # over.time.vars = # # # First, ensure we have lists. # if (!is.list(xlim[[space]])) # xlim[[space]] = list(xlim[[space]]) # # if (!is.list(ylim[[space]])) # ylim[[space]] = list(ylim[[space]]) # # # Here, you allways have to specify limits for every plot - if you specify # # some limits. # assertList(ylim[[space]], len = ) # assertList(ylim[[space]], # # for (i in seq_along(get(space))) { # # op.frame = if (space == "x.over.time") op.x else op.y # var.names = if (space == "x.over.time") x.over.time[[i]] else y.over.time[[i]] # op.frame = op.frame[, var.names, drop = FALSE] # # # lim.x is iteration number here. If NULL, use ggplot defaults, else check. # if (is.null(xlim[[space]][[i]])) { # xlim[[space]][[i]] = c(NA_real_, NA_real_) # } else { # asInteger(xlim[[space]][[i]], len = 2) # } # # # lim.y as minimum and maximum of all plotted variables: # if (is.null(ylim[[space]][[i]])) { # ylim[[space]][[i]] = range(op.frame) # ylim[[space]][[i]] = c(-1, 1) * scale * abs(diff(ylim[[space]][[i]])) + ylim[[space]][[i]] # } else { # assertNumeric(ylim[[space]][[i]], len = 2L, any.missing = FALSE) # } # # } # } return(list(xlim = xlim, ylim = ylim)) } # Function to impute missing values. imputeMissingValues = function(x, impute.scale, impute.value) { na.index = which(is.na(x)) if (length(na.index) > 0) { if (inherits(x, "numeric")) { x[na.index] = max(x, na.rm = TRUE) + impute.scale * (diff(range(x, na.rm = TRUE))) } if (inherits(x, "factor")) { levels(x) = c(levels(x), impute.value) x[na.index] = impute.value } } return(x) } # subset rows and cols of the opt.path and return list with data.frames for # x and y space and the subsets. # returns list with dataframes for x and y space, vectors for dob, type and alpha # character vector for x and y names getAndSubsetPlotData = function(op, iters, subset.obs, subset.vars, subset.targets, marked = NULL, alpha = TRUE, impute.scale = 0.05, impute.value = "missing", ...) { # extract initial information and the data from the opt.path x.names = colnames(getOptPathX(op)) y.names = op$y.names dim.x = length(x.names) iters.max = max(getOptPathDOB(op)) op.x = as.data.frame(op, include.x = TRUE, include.y = FALSE, include.rest = FALSE, dob = 0:max(iters), eol = c(min(iters):iters.max, NA)) op.y = as.data.frame(op, include.x = FALSE, include.y = TRUE, include.rest = FALSE, dob = 0:max(iters), eol = c(min(iters):iters.max, NA)) op.rest = as.data.frame(op, include.x = FALSE, include.y = FALSE, include.rest = TRUE, dob = 0:max(iters), eol = c(min(iters):iters.max, NA)) dob = getOptPathDOB(op, dob = 0:max(iters), eol = c((max(iters) + 1):iters.max, NA)) # mark best point / pareto front if marked = "best" if (is.character(marked)) { if (length(y.names) == 1) { marked = getOptPathBestIndex(op) } else { marked = getOptPathParetoFront(op, index = TRUE) } } # make sure that only points are marked that are alive at this iteration marked = marked[marked <= nrow(op.x)] # set alpha and type values .alpha = if (alpha && max(iters) > 0) { normalize(dob, "range", range = c(1 / (max(iters) + 1), 1)) } else { rep(1, length(dob)) } .type = as.factor(ifelse(dob == 0, "init", ifelse(dob == max(iters), "prop", "seq"))) .type = factor(.type, levels = c("init", "seq", "prop", "marked")) if (!is.null(marked)) { .type[marked] = "marked" } .alpha = pmax(0.1, .alpha) # Check and calculate the subsets if (missing(subset.obs)) { subset.obs = 1:nrow(op.x) } assertIntegerish(subset.obs, lower = 1, upper = getOptPathLength(op), unique = TRUE, any.missing = FALSE) # use only indices avaible in the current iterations subset.obs = subset.obs[subset.obs <= nrow(op.x)] if (missing(subset.vars)) { subset.vars = x.names } if (is.numeric(subset.vars)) { assertIntegerish(subset.vars, lower = 1, upper = dim.x, unique = TRUE, any.missing = FALSE) } else { assertSubset(subset.vars, x.names) } if (missing(subset.targets)) { subset.targets = y.names } if (is.numeric(subset.targets)) { assertIntegerish(subset.targets, lower = 1, upper = getOptPathLength(op), unique = TRUE, any.missing = FALSE) } else { assertSubset(subset.targets, y.names) } # impute missing values - don't impute in op.rest! op.x = BBmisc::dapply(op.x, fun = imputeMissingValues, impute.scale = impute.scale, impute.value = impute.value) op.y = BBmisc::dapply(op.y, fun = imputeMissingValues, impute.scale = impute.scale, impute.value = impute.value) # now subset everything op.x = op.x[subset.obs, subset.vars, drop = FALSE] op.y = op.y[subset.obs, subset.targets, drop = FALSE] op.rest = op.rest[subset.obs, -(1:2), drop = FALSE] dob = dob[subset.obs] .alpha = .alpha[subset.obs] .type = .type[subset.obs] x.names = if (is.numeric(subset.vars)) x.names[subset.vars] else subset.vars y.names = if (is.numeric(subset.targets)) y.names[subset.targets] else subset.targets return( list( op.x = op.x, op.y = op.y, op.rest = op.rest, dob = dob, .alpha = .alpha, .type = .type, x.names = x.names, y.names = y.names, rest.names = names(op.rest) ) ) } # Helper to get cumulated exec.time getOptPathColAtTimes = function(op, times) { requirePackages("plyr") if (!is.data.frame(op)) { op = as.data.frame(op) } assertNumeric(op$exec.time) op$exec.time.sum = cumsum(op$exec.time) op$finished = c(rep(FALSE, times = nrow(op) - 1), TRUE) plyr::adply(times, 1, getOptPathColAtTime, op = op) } getOptPathColAtTime = function(op.df, time) { col = op.df[which.last(op.df$exec.time.sum <= time), ] if (nrow(col) == 1) col$time = time col } ParamHelpers/R/hasType.R0000644000176000001440000000324713633666270014650 0ustar ripleyusers#' @title Check whether parameter set contains a certain type. #' #' @description `TRUE` if the parameter set contains at least one parameter of #' the mentioned type x. Type x always subsumes x and x-vector. #' #' @template arg_parset #' @template arg_include_int #' @template arg_include_logical #' @return `logical(1)` #' @name hasType #' @rdname hasType NULL #' @export #' @rdname hasType hasDiscrete = function(par.set, include.logical = TRUE) { assertClass(par.set, "ParamSet") hasSomeParamsOfTypes(par.set, types = getTypeStringsDiscrete(include.logical = include.logical)) } #' @export #' @rdname hasType hasInteger = function(par.set) { assertClass(par.set, "ParamSet") hasSomeParamsOfTypes(par.set, types = getTypeStringsInteger()) } #' @export #' @rdname hasType hasLogical = function(par.set) { assertClass(par.set, "ParamSet") hasSomeParamsOfTypes(par.set, types = getTypeStringsLogical()) } #' @export #' @rdname hasType hasCharacter = function(par.set) { assertClass(par.set, "ParamSet") hasSomeParamsOfTypes(par.set, types = getTypeStringsCharacter()) } #' @export #' @rdname hasType hasNumeric = function(par.set, include.int = TRUE) { assertClass(par.set, "ParamSet") hasSomeParamsOfTypes(par.set, types = getTypeStringsNumeric(include.int = include.int)) } ##### helpers # is at least one of types somewhere in par.set? hasSomeParamsOfTypes = function(par.set, types) { any(getParamTypes(par.set, df.cols = FALSE, with.nr = FALSE, use.names = FALSE) %fin% types) } # are all param types contained in 'types' hasAllParamsOfTypes = function(par.set, types) { all(getParamTypes(par.set, df.cols = FALSE, with.nr = FALSE, use.names = FALSE) %fin% types) } ParamHelpers/R/makeParamFuns.R0000644000176000001440000001101713633666270015757 0ustar ripleyusers#' @rdname Param #' @export makeNumericParam = function(id, lower = -Inf, upper = Inf, allow.inf = FALSE, default, trafo = NULL, requires = NULL, tunable = TRUE, special.vals = list()) { makeParam(id = id, type = "numeric", learner.param = FALSE, lower = lower, upper = upper, allow.inf = allow.inf, default = default, trafo = trafo, requires = requires, tunable = tunable, special.vals = special.vals) } #' @rdname Param #' @export makeNumericVectorParam = function(id, len, lower = -Inf, upper = Inf, cnames = NULL, allow.inf = FALSE, default, trafo = NULL, requires = NULL, tunable = TRUE, special.vals = list()) { makeParam(id = id, type = "numericvector", learner.param = FALSE, len = len, lower = lower, upper = upper, cnames = cnames, allow.inf = allow.inf, default = default, trafo = trafo, requires = requires, tunable = tunable, special.vals = special.vals) } #' @rdname Param #' @export makeIntegerParam = function(id, lower = -Inf, upper = Inf, default, trafo = NULL, requires = NULL, tunable = TRUE, special.vals = list()) { makeParam(id = id, type = "integer", learner.param = FALSE, lower = lower, upper = upper, default = default, trafo = trafo, requires = requires, tunable = tunable, special.vals = special.vals) } #' @rdname Param #' @export makeIntegerVectorParam = function(id, len, lower = -Inf, upper = Inf, cnames = NULL, default, trafo = NULL, requires = NULL, tunable = TRUE, special.vals = list()) { makeParam(id = id, type = "integervector", learner.param = FALSE, len = len, lower = lower, upper = upper, cnames = cnames, default = default, trafo = trafo, requires = requires, tunable = tunable, special.vals = special.vals) } #' @rdname Param #' @export makeLogicalParam = function(id, default, requires = NULL, tunable = TRUE, special.vals = list()) { values = list("TRUE" = TRUE, "FALSE" = FALSE) makeParam(id = id, type = "logical", learner.param = FALSE, values = values, default = default, trafo = NULL, requires = requires, tunable = tunable, special.vals = special.vals) } #' @rdname Param #' @export makeLogicalVectorParam = function(id, len, cnames = NULL, default, requires = NULL, tunable = TRUE, special.vals = list()) { values = list("TRUE" = TRUE, "FALSE" = FALSE) makeParam(id = id, type = "logicalvector", learner.param = FALSE, len = len, values = values, cnames = cnames, default = default, trafo = NULL, requires = requires, tunable = tunable, special.vals = special.vals) } #' @rdname Param #' @export makeDiscreteParam = function(id, values, trafo = NULL, default, requires = NULL, tunable = TRUE, special.vals = list()) { makeParam(id = id, type = "discrete", learner.param = FALSE, values = values, default = default, trafo = trafo, requires = requires, tunable = tunable, special.vals = special.vals) } #' @rdname Param #' @export makeDiscreteVectorParam = function(id, len, values, trafo = NULL, default, requires = NULL, tunable = TRUE, special.vals = list()) { makeParam(id = id, type = "discretevector", learner.param = FALSE, len = len, values = values, default = default, trafo = trafo, requires = requires, tunable = tunable, special.vals = special.vals) } #' @rdname Param #' @export makeFunctionParam = function(id, default = default, requires = NULL, special.vals = list()) { makeParam(id = id, type = "function", learner.param = FALSE, values = NULL, default = default, trafo = NULL, requires = requires, tunable = FALSE, special.vals = special.vals) } # FIXME: what happens if NA is later used for untyped params? because we might interpret this as # missing value wrt. dependent params #' @rdname Param #' @export makeUntypedParam = function(id, default, requires = NULL, tunable = TRUE, special.vals = list()) { makeParam(id = id, type = "untyped", learner.param = FALSE, values = NULL, default = default, trafo = NULL, requires = requires, tunable = TRUE, special.vals = special.vals) } #' @rdname Param #' @export makeCharacterParam = function(id, default, requires = NULL, special.vals = list()) { makeParam(id = id, type = "character", learner.param = FALSE, default = default, trafo = NULL, requires = requires, tunable = FALSE, special.vals = special.vals) } #' @rdname Param #' @export makeCharacterVectorParam = function(id, len, cnames = NULL, default, requires = NULL, special.vals = list()) { makeParam(id = id, type = "charactervector", learner.param = FALSE, len = len, cnames = cnames, default = default, trafo = NULL, requires = requires, tunable = FALSE, special.vals = special.vals) } ParamHelpers/R/getParamTypeCounts.R0000644000176000001440000000103513633666270017022 0ustar ripleyusers#' Returns information on the number of parameters of a each type. #' #' @template arg_parset #' @return [`list`] #' Named list which contains for each supported parameter type the #' number of parameters of this type in the given ParamSet. #' @export getParamTypeCounts = function(par.set) { assertClass(par.set, "ParamSet") supported.types = getTypeStringsAll() par.types = getParamTypes(par.set) count = lapply(supported.types, function(type) { sum(par.types == type) }) names(count) = supported.types return(count) } ParamHelpers/R/getDefaults.R0000644000176000001440000000772513633666270015507 0ustar ripleyusers#' @title Return defaults of parameters in parameter set. #' #' @description #' Return defaults of single parameters or parameters in a parameter set or a list of parameters. #' #' @param obj ([Param()] | [ParamSet()] | `list`)\cr #' Parameter, parameter set or list of parameters, whose defaults should be #' extracted. In case the default values contain expressions, they will be #' evaluated using the provided dictionary (`dict`). #' @param include.null (`logical(1)`)\cr #' Include `NULL` entries for parameters without default values in the result #' list? Note that this can be slightly dangerous as `NULL` might be used as #' default value for other parameters. Default is `FALSE`. #' @template arg_dict #' @return named `list`. Named (and in case of a [ParamSet()], in the same order). #' Parameters without defaults are not present in the list. #' @examples #' ps1 = makeParamSet( #' makeDiscreteParam("x", values = c("a", "b"), default = "a"), #' makeNumericVectorParam("y", len = 2), #' makeIntegerParam("z", default = 99) #' ) #' getDefaults(ps1, include.null = TRUE) #' #' ps2 = makeParamSet( #' makeNumericVectorParam("a", len = expression(k), default = expression(p)), #' makeIntegerParam("b", default = 99), #' makeLogicalParam("c") #' ) #' getDefaults(ps2, dict = list(k = 3, p = 5.4)) #' @export getDefaults = function(obj, include.null = FALSE, dict = NULL) { UseMethod("getDefaults") } #' @export getDefaults.Param = function(obj, include.null = FALSE, dict = NULL) { assertClass(obj, "Param") assertFlag(include.null) assertList(dict, names = "unique", null.ok = TRUE) # no param = no default if (length(obj) == 0L) { return(NULL) } def = obj$default if (is.null(def) || !obj$has.default) { return(NULL) } if (is.expression(def)) { def = eval(def, envir = dict) } # evaluate length in case it is defined with an expression if (is.expression(obj$len)) { obj$len = getParamLengths(par = obj, dict = dict) } # replicate default according to length of param if ((length(def) == 1L) && !is.na(obj$len) && obj$len > 1L) { def = rep(def, obj$len) } return(def) } #' @export getDefaults.ParamSet = function(obj, include.null = FALSE, dict = NULL) { assertClass(obj, "ParamSet") assertFlag(include.null) assertList(dict, names = "unique", null.ok = TRUE) # if the ParamSet is empty, there are no defaults if (isEmpty(obj)) { return(list()) } # extract list with defaults of all params defs = extractSubList(obj$pars, "default", simplify = FALSE) if (!include.null) { # if all defaults are NULL (and NULLs are not allowed) return empty list if (all(vlapply(defs, is.null))) { return(list()) } j = vlapply(obj$pars, function(x) x$has.default) if (!any(j)) { return(list()) } # extract ids of params with non-NULL defaults ids = names(defs)[j] } else { # consider all params ids = names(defs) } # extract defaults of all considerable params setNames(lapply(obj$pars[ids], getDefaults, include.null = include.null, dict = dict), ids) } #' @export getDefaults.list = function(obj, include.null = FALSE, dict = NULL) { assertClass(obj, "list") assertFlag(include.null) assertList(dict, names = "unique", null.ok = TRUE) # if the list is empty, there are no defaults if (length(obj) == 0L) { return(list()) } # extract list with defaults of all params defs = extractSubList(obj, "default", simplify = FALSE) if (!include.null) { # if all defaults are NULL (and NULLs are not allowed) return empty list if (all(vlapply(defs, is.null))) { return(list()) } j = vlapply(obj, function(x) x$has.default) if (!any(j)) { return(list()) } # extract ids of params with non-NULL defaults ids = names(defs)[j] } else { # consider all params ids = names(defs) } # extract defaults of all considerable params setNames(lapply(obj[j], getDefaults, include.null = include.null, dict = dict), ids) } ParamHelpers/R/OptPath.R0000644000176000001440000001303713633666270014610 0ustar ripleyusers#' @title Create optimization path. #' #' @description Optimizers can iteratively log their evaluated points into this #' object. Can be converted into a data.frame with `as.data.frame(x, #' discretes.as.factor = TRUE / FALSE)`. #' #' A optimization path has a number of path elements, where each element #' consists of: the value of the decision variables at this point, the values of #' the performance measures at this point, the date-of-birth (dob) of this #' point, the end-of-life (eol) of this point and possibly an error message. See #' also [addOptPathEl()]. #' #' For discrete parameters always the name of the value is stored as a #' character. When you retrieve an element with [getOptPathEl()], this name is #' converted to the actual discrete value. #' #' If parameters have associated transformation you are free to decide whether #' you want to add x values before or after transformation, see argument #' `add.transformed.x` and [trafoOptPath()]. #' #' The S3 class is a list which stores at least these elements: #' \describe{ #' \item{par.set [ParamSet()]}{See argument of same name.} #' \item{y.names [`character`]}{See argument of same name.} #' \item{minimize [`logical`]}{See argument of same name.} #' \item{add.transformed.x `logical(1)`}{See argument of same name.} #' \item{env [`environment`]}{Environment which stores the optimization path. #' Contents depend on implementation.} #' } #' #' @template arg_parset #' @param y.names (`character`)\cr #' Names of performance measures that are optimized or logged. #' @param minimize (`logical`)\cr #' Which of the performance measures in y.names should be minimized? #' Vector of booleans in the same order as `y.names`. #' @param add.transformed.x (`logical(1)`)\cr #' If some parameters have associated transformations, are you going to add x #' values after they have been transformed? Default is `FALSE`. #' @param include.error.message (`logical(1)`)\cr #' Should it be possible to include an error message string (or NA if no error #' occurred) into the path for each evaluation? This is useful if you have #' complex, long running objective evaluations that might fail. Default is #' `FALSE`. #' @param include.exec.time (`logical(1)`)\cr #' Should it be possible to include execution time of evaluations into the #' path for each evaluation? Note that execution time could also be entered in #' `y.names` as a direct performance measure. If you use this option here, #' time is regarded as an extra measurement you might be curious about. #' Default is `FALSE`. #' @param include.extra (`logical(1)`)\cr #' Should it be possible to include extra info #' into the path for each evaluation? #' Default is `FALSE`. #' @name OptPath #' @rdname OptPath #' @family optpath NULL makeOptPath = function(par.set, y.names, minimize, add.transformed.x = FALSE, include.error.message = FALSE, include.exec.time = FALSE, include.extra = FALSE) { n.y = length(y.names) ok = c("numeric", "integer", "numericvector", "integervector", "logical", "logicalvector", "discrete", "discretevector", "character", "charactervector") if (length(par.set$pars) > length(filterParams(par.set, type = ok)$pars)) { stop("OptPath can currently only be used for: ", paste(ok, collapse = ",")) } x.names = getParamIds(par.set) # be really sure that x and y columns are uniquely named x.names2 = c(getParamIds(par.set, with.nr = TRUE), getParamIds(par.set, with.nr = FALSE)) if (length(intersect(x.names2, y.names)) > 0) { stop("'x.names' and 'y.names' must not contain common elements!") } if (length(minimize) != n.y) { stop("'y.names' and 'minimize' must be of the same length!") } if (is.character(names(minimize)) && !setequal(names(minimize), y.names)) { stop("Given names for 'minimize' must be the same as 'y.names'!") } if (is.null(names(minimize))) { names(minimize) = y.names } if (any(c("dob", "eol", "error.message") %in% (union(x.names, y.names)))) { stop("'dob', 'eol' and 'error.message' are not allowed in parameter names or 'y.names'!") } ee = new.env(parent = emptyenv()) ee$dob = ee$eol = integer(0) # potentially init error.message and exec.time in env ee$error.message = if (include.error.message) character(0L) else NULL ee$exec.time = if (include.exec.time) numeric(0L) else NULL ee$extra = if (include.extra) list() else NULL makeS3Obj("OptPath", par.set = par.set, y.names = y.names, minimize = minimize, add.transformed.x = add.transformed.x, env = ee ) } #' @export print.OptPath = function(x, ...) { n = getOptPathLength(x) em = x$env$error.message et = x$env$exec.time ex = x$env$extra catf("Optimization path") catf(" Dimensions: x = %i/%i, y = %i", length(x$par.set$pars), sum(getParamLengths(x$par.set)), length(x$y.names)) catf(" Length: %i", n) catf(" Add x values transformed: %s", x$add.transformed.x) s = if (is.null(em)) "" else sprintf(" Errors: %i / %i.", sum(!is.na(em)), n) catf(" Error messages: %s.%s", !is.null(em), s) s = if (is.null(et)) { s = "" } else { ntimes = sum(!is.na(et)) ntime.nas = length(et) - ntimes # no non-na exec times in path if (ntimes == 0L) { et1 = 0 et2 = 0 } else { et1 = min(et, na.rm = TRUE) et2 = max(et, na.rm = TRUE) } s = sprintf(" Range: %g - %g. %i NAs.", et1, et2, ntime.nas) } catf(" Exec times: %s.%s", !is.null(et), s) if (!is.null(ex)) { nondot.extra.length = ifelse(length(ex) > 0L, length(removeDotEntries(ex[[1L]])), NA) catf(" Extras: %i columns", nondot.extra.length) } } ParamHelpers/R/LearnerParam.R0000644000176000001440000000237513633666270015605 0ustar ripleyusers#' @title Create a description object for a parameter of a machine learning #' algorithm. #' #' @description This specializes [Param()] by adding a few more attributes, like #' a default value, whether it refers to a training or a predict function, etc. #' Note that you can set `length` to `NA` #' #' The S3 class is a [Param()] which additionally stores these elements: #' \describe{ #' \item{when `character(1)`}{See argument of same name.} #' } #' #' See the note in [Param()] about being able to pass expressions to certain arguments. #' #' @inheritParams Param #' @param len (`integer(1)`)\cr #' Length of vector parameter. #' Can be set to `NA` to define a vector with unspecified length. #' @param when (`character(1)`)\cr #' Specifies when parameter is used in the learner: \dQuote{train}, #' \dQuote{predict} or \dQuote{both}. Default is \dQuote{train}. #' @return [LearnerParam()]. #' @name LearnerParam #' @rdname LearnerParam NULL makeLearnerParam = function(p, when) { assertChoice(when, c("train", "predict", "both")) p$when = when class(p) = c("LearnerParam", "Param") return(p) } #' @export print.LearnerParam = function(x, ..., trafo = TRUE, used = TRUE) { print.Param(x, trafo = trafo) if (used) { catf("Used: %s.", x$when) } } ParamHelpers/R/filterParams.R0000644000176000001440000000742513633666270015666 0ustar ripleyusers#' @title Get parameter subset of only certain parameters. #' #' @description #' Parameter order is not changed. It is possible to filter via multiple #' arguments, e.g., first filter based on id, then the type and lastly tunable. #' The order in which the filters are executed is always fixed (id > type > #' tunable). #' #' @template arg_parset #' @param ids (`NULL` | `character`)\cr #' Vector with id strings containing the parameters to select. Has to be a #' subset of the parameter names within the parameter set. #' Per default (`ids = NULL`) no filtering based on names is done. #' @param type (`NULL` | `character`)\cr #' Vector of allowed types, subset of: \dQuote{numeric}, \dQuote{integer}, #' \dQuote{numericvector}, \dQuote{integervector}, \dQuote{discrete}, #' \dQuote{discretevector}, \dQuote{logical}, \dQuote{logicalvector}, #' \dQuote{character}, \dQuote{charactervector}, \dQuote{function}, #' \dQuote{untyped}. #' Setting `type = NULL`, which is the default, allows the consideration of all types. #' @param tunable (`logical`)\cr #' Vector of allowed values for the property `tunable`. Accepted arguments are #' `TRUE`, `FALSE` or `c(TRUE, FALSE)`. The default is `c(TRUE, FALSE)`, i.e. #' none of the parameters will be filtered out. #' @param check.requires (`logical(1)`)\cr #' Toggle whether it should be checked that all requirements in the #' (ParamSet()) are still valid after filtering or not. This check is done #' after filtering and will throw an error if those Params are filtered which #' other Params need for their requirements. Default is `FALSE`. #' @return [ParamSet()]. #' @examples #' ps = makeParamSet( #' makeNumericParam("u", lower = 1), #' makeIntegerParam("v", lower = 1, upper = 2), #' makeDiscreteParam("w", values = 1:2), #' makeLogicalParam("x"), #' makeCharacterParam("s"), #' makeNumericParam("y", tunable = FALSE) #' ) #' #' # filter for numeric and integer parameters #' filterParams(ps, type = c("integer", "numeric")) #' #' # filter for tunable, numeric parameters #' filterParams(ps, type = "numeric", tunable = TRUE) #' #' # filter for all numeric parameters among "u", "v" and "x" #' filterParams(ps, type = "numeric", ids = c("u", "v", "x")) #' @export filterParams = function(par.set, ids = NULL, type = NULL, tunable = c(TRUE, FALSE), check.requires = FALSE) { # if (!is.null(par.set$forbidden)) # stopf("Operation not allowed for param set with forbidden region currently!") if (!is.null(ids)) { assertSubset(ids, names(par.set$pars)) par.set$pars = Filter(function(p) p$id %in% ids, par.set$pars) } if (!is.null(type)) { assertSubset(type, getTypeStringsAll()) par.set$pars = Filter(function(p) p$type %in% type, par.set$pars) } assertLogical(tunable, min.len = 1L, max.len = 2L, unique = TRUE) par.set$pars = Filter(function(p) p$tunable %in% tunable, par.set$pars) if (check.requires) { # find all vars which are in each params requirements which are not part of the param.set missing.vars = setdiff(getRequiredParamNames(par.set), getParamIds(par.set)) if (length(missing.vars) > 0) { stopf("Params %s filtered but needed for requirements of present Params", collapse(missing.vars)) } } return(par.set) } #' @template arg_include_int #' @rdname filterParams #' @export filterParamsNumeric = function(par.set, ids = NULL, tunable = c(TRUE, FALSE), include.int = TRUE) { filterParams(par.set, ids = ids, tunable = tunable, type = getTypeStringsNumeric(include.int = include.int)) } #' @template arg_include_logical #' @rdname filterParams #' @export filterParamsDiscrete = function(par.set, ids = NULL, tunable = c(TRUE, FALSE), include.logical = TRUE) { filterParams(par.set, ids = ids, tunable = tunable, type = getTypeStringsDiscrete(include.logical = include.logical)) } ParamHelpers/R/trafo.R0000644000176000001440000000637213633666270014350 0ustar ripleyusers#' @title Transform a value. #' #' @description #' Transform a value with associated transformation function(s). #' #' @template arg_par_or_set #' @param x (any) \cr #' Single value to check. For a parameter set this must be a list. If the list #' is unnamed (not recommended) it must be in the same order as the param set. #' If it is named, its names must match the parameter names in the param set. #' @return Transformed value. #' @export #' @examples #' # transform simple parameter: #' p = makeNumericParam(id = "x", trafo = function(x) x^2) #' trafoValue(p, 2) #' # for a parameter set different transformation functions are possible: #' ps = makeParamSet( #' makeIntegerParam("u", trafo = function(x) 2 * x), #' makeNumericVectorParam("v", len = 2, trafo = function(x) x / sum(x)), #' makeDiscreteParam("w", values = c("a", "b")) #' ) #' # now the values of "u" and "v" are transformed: #' trafoValue(ps, list(3, c(2, 4), "a")) trafoValue = function(par, x) { if (inherits(par, "ParamSet")) { assertList(x, len = getParamNr(par)) pids = getParamIds(par) if (is.null(names(x))) { # if we dont have names, assume list is in correct order and matches parset names(x) = pids } else { # if we have names, they must match the names in parset, and we reorder to be "safe" # and an later rely on the order assertSetEqual(names(x), pids) x = x[pids] } Map(trafoValue, par$pars, x) } else { if (is.null(par$trafo)) { x } else { par$trafo(x) } } } #' Transform optimization path. #' #' Transform optimization path with associated transformation functions of parameters. #' Can only be done when x values where added \dQuote{untransformed}. #' #' @param opt.path [[OptPath()]]\cr #' Optimization path. #' @return [[OptPath()]]. #' @export #' @examples #' ps = makeParamSet( #' makeIntegerParam("u", trafo = function(x) 2 * x), #' makeNumericVectorParam("v", len = 2, trafo = function(x) x / sum(x)), #' makeDiscreteParam("w", values = c("a", "b")) #' ) #' op = makeOptPathDF(ps, y.names = "y", minimize = TRUE) #' addOptPathEl(op, x = list(3, c(2, 4), "a"), y = 0, dob = 1, eol = 1) #' addOptPathEl(op, x = list(4, c(5, 3), "b"), y = 2, dob = 5, eol = 7) #' #' as.data.frame(op) #' op = trafoOptPath(op) #' as.data.frame(op) trafoOptPath = function(opt.path) { assertClass(opt.path, "OptPath") if (opt.path$add.transformed.x) { stop("Cannot further trafo opt.path, you already added transformed x values to it!") } ps = opt.path$par.set # FIXME: this only works for the DF implementation! op2 = makeOptPathDF(opt.path$par.set, opt.path$y.names, opt.path$minimize, add.transformed.x = TRUE, include.error.message = !is.null(opt.path$env$error.message), include.exec.time = !is.null(opt.path$env$exec.time), include.extra = !is.null(opt.path$env$extra)) lapply(1:getOptPathLength(opt.path), function(i) { z = getOptPathEl(opt.path, i) x = trafoValue(ps, z$x) args = list(op = op2, x = x, y = z$y, dob = z$dob, eol = z$eol) # the next components can possibly be NULL, will be only added to arg list, if they are "there" args$error.message = z$error.message args$exec.time = z$exec.time args$extra = z$extra do.call(addOptPathEl, args) }) return(op2) } ParamHelpers/R/dropParams.R0000644000176000001440000000063613633666270015342 0ustar ripleyusers#' Drop Params from ParamSet by ids. #' #' @template arg_parset #' @param drop (`character`)\cr #' `id`s of the [Param()]s in the [ParamSet()] to drop from the ParamSet. #' @return [[ParamSet()]]. #' @export dropParams = function(par.set, drop) { assertClass(par.set, "ParamSet") assertSubset(drop, getParamIds(par.set)) par.set$pars = Filter(function(p) p$id %nin% drop, par.set$pars) return(par.set) } ParamHelpers/R/hasTrafo.R0000644000176000001440000000070113633666270014772 0ustar ripleyusers#' @title Check parameter / parameter set for trafos. #' #' @description #' `TRUE` iff the parameter has any trafos or any parameter in the set has #' trafos. #' #' @template arg_par_or_set #' @return `logical(1)`. #' @export hasTrafo = function(par) { UseMethod("hasTrafo") } #' @export hasTrafo.Param = function(par) { return(!is.null(par$trafo)) } #' @export hasTrafo.ParamSet = function(par) { return(any(vlapply(par$pars, hasTrafo))) } ParamHelpers/R/convertTypesToCInts.R0000644000176000001440000000021213414125445017160 0ustar ripleyusers# integer encoding of types for easier use convertTypesToCInts = function(types) { fmatch(types, ph$convert.to.ctypes, nomatch = 99L) } ParamHelpers/R/listToDfOneRow.R0000644000176000001440000000127513636346430016110 0ustar ripleyusers#' @title Convert a list to a data.frame with one row #' #' @description #' Convert a list of vectors or scalars to a `data.frame` with only one row. Names of the columns correspond to #' the names of elements in the list. If a vector is one list element it is spread over multiple #' columns and named sequentially, e.g. `a = c(5,7)` becomes `data.frame(a1 = 5, a2 = 7)`. #' #' @param l (`list`)\cr #' of atomic values of vectors. #' @return (`data.frame`) with only one row, containing the list elements. listToDfOneRow = function(l) { assertList(l, min.len = 1) lapply(l, assert_atomic_vector) l = lapply(seq_along(l), function(x) t(unlist(l[x]))) data.frame(l, stringsAsFactors = TRUE) } ParamHelpers/R/getParamSet.R0000644000176000001440000000050413633666270015440 0ustar ripleyusers#' @title Get parameter set. #' #' @description `getParamSet` is a generic and can be called to extract the #' `ParamSet` from different objects. #' #' @param x (`object`) \cr #' Object to extract the ParamSet from. #' @return [ParamHelpers::ParamSet()] #' @export getParamSet = function(x) { UseMethod("getParamSet") } ParamHelpers/R/generateDesignOfDefaults.R0000644000176000001440000000425513633666270020134 0ustar ripleyusers#' @title Generates a design with the defaults of a parameter set. #' #' @description #' The following types of columns are created: #' \tabular{ll}{ #' numeric(vector) \tab `numeric` \cr #' integer(vector) \tab `integer` \cr #' discrete(vector) \tab `factor` (names of values = levels) \cr #' logical(vector) \tab `logical` #' } #' This will create a design containing only one point at the default values of #' the supplied param set. In most cases you will combine the resulting #' `data.frame` with a different generation function e.g. [generateDesign()], #' [generateRandomDesign()] or [generateGridDesign()]. This is useful to force #' an evaluation at the default location of the parameters while still #' generating a design. Parameters default values, whose conditions (`requires`) #' are not fulfilled will be set to `NA` in the result. #' @template arg_parset #' @template arg_trafo #' @template ret_gendes_df #' @export generateDesignOfDefaults = function(par.set, trafo = FALSE) { doBasicGenDesignChecks(par.set) assertFlag(trafo) pars = par.set$pars defaults = getDefaults(par.set) diff = setdiff(names(pars), names(defaults)) if (length(diff) > 0) { stopf("No default parameter setting for: %s", collapse(diff)) } # check if one or more default values are special values special.default = mapply(FUN = function(p, value) isSpecialValue(par.set$pars[[p]], value), p = names(defaults), value = defaults, SIMPLIFY = TRUE) if (any(special.default)) { stopf("special.vals as default for Parameter(s): %s", collapse(names(defaults)[special.default])) } # convert discrete value here to names, to we can stuff them into a df defaults = mapply(FUN = function(p, d) { if (isDiscrete(p, include.logical = FALSE)) discreteValueToName(p, d) else d }, par.set$pars, defaults, SIMPLIFY = FALSE) res = listToDfOneRow(defaults) # now trafo and set params whose conditions are not fulfilled to NA # if (trafo) { res = applyTrafos(res, pars) } if (hasRequires(par.set)) { res = setRequiresToNA(res, pars) } res = fixDesignFactors(res, par.set) res = fixDesignVarTypes(res, par.set) attr(res, "trafo") = trafo return(res) } ParamHelpers/R/OptPath_getter.R0000644000176000001440000001770313633666270016166 0ustar ripleyusers#' @title Get the length of the optimization path. #' #' @description #' Dependent parameters whose requirements are not satisfied are represented by a scalar #' NA in the output. #' #' @template arg_op #' @return `integer(1)` #' @export #' @family optpath getOptPathLength = function(op) { UseMethod("getOptPathLength") } #' @title Get an element from the optimization path. #' #' @description #' Dependent parameters whose requirements are not satisfied are represented by a scalar NA #' in the elements of `x` of the return value. #' #' @template arg_op #' @param index (`integer(1)`)\cr #' Index of element. #' @return List with elements `x` (named `list`), `y` (named `numeric`), #' `dob` `integer(1)`, `eol` `integer(1)`. #' The elements `error.message` (`character(1)`), #' `exec.time` (`numeric(1)`) and `extra` (named `list`) are #' there if the respective options in [OptPath()] are enabled. #' @rdname getOptPathEl #' @export #' @family optpath getOptPathEl = function(op, index) { UseMethod("getOptPathEl") } #' Get data.frame of input points (X-space) referring to the param set from the optimization path. #' #' @template arg_op #' @template arg_opgetter_dob #' @template arg_opgetter_eol #' @return [data.frame]. #' @export #' @family optpath getOptPathX = function(op, dob, eol) { UseMethod("getOptPathX") } #' Get y-vector or y-matrix from the optimization path. #' #' @template arg_op #' @param names [character]\cr #' Names of performance measure. #' Default is all performance measures in path. #' @template arg_opgetter_dob #' @template arg_opgetter_eol #' @param drop (`logical(1)`)\cr #' Return vector instead of matrix when only one y-column was selected? #' Default is `TRUE`. #' @return (`numeric` | `matrix`). The columns of the matrix are always named. #' @export #' @family optpath getOptPathY = function(op, names, dob, eol, drop = TRUE) { UseMethod("getOptPathY") } #' Get date-of-birth vector from the optimization path. #' #' @template arg_op #' @template arg_opgetter_dob #' @template arg_opgetter_eol #' @return [integer]. #' @export #' @family optpath getOptPathDOB = function(op, dob, eol) { UseMethod("getOptPathDOB") } #' Get end-of-life vector from the optimization path. #' #' @template arg_op #' @template arg_opgetter_dob #' @template arg_opgetter_eol #' @return [integer]. #' @export #' @family optpath getOptPathEOL = function(op, dob, eol) { UseMethod("getOptPathEOL") } #' Get error-message vector from the optimization path. #' #' @template arg_op #' @template arg_opgetter_dob #' @template arg_opgetter_eol #' @return [character]. #' @export #' @family optpath getOptPathErrorMessages = function(op, dob, eol) { UseMethod("getOptPathErrorMessages") } #' Get exec-time vector from the optimization path. #' #' @template arg_op #' @template arg_opgetter_dob #' @template arg_opgetter_eol #' @return [numeric]. #' @export #' @family optpath getOptPathExecTimes = function(op, dob, eol) { UseMethod("getOptPathExecTimes") } #' Get column from the optimization path. #' #' @template arg_op #' @param name (`character(1)`)\cr #' Name of the column. #' @template arg_opgetter_dob #' @template arg_opgetter_eol #' @return Single column as a vector. #' @export #' @family optpath getOptPathCol = function(op, name, dob, eol) { UseMethod("getOptPathCol") } #' Get columns from the optimization path. #' #' @template arg_op #' @param names [character]\cr #' Names of the columns. #' @template arg_opgetter_dob #' @template arg_opgetter_eol #' @inheritParams as.data.frame.OptPathDF #' @return [data.frame]. #' @export #' @family optpath getOptPathCols = function(op, names, dob, eol, row.names = NULL) { UseMethod("getOptPathCols") } #' Get index of the best element from optimization path. #' #' @template arg_op #' @param y.name (`character(1)`)\cr #' Name of target value to decide which element is best. #' Default is `y.names[1]`. #' @template arg_opgetter_dob #' @template arg_opgetter_eol #' @param ties (`character(1)`)\cr #' How should ties be broken when more than one optimal element is found? #' \dQuote{all}: return all indices, #' \dQuote{first}: return first optimal element in path, #' \dQuote{last}: return last optimal element in path, #' \dQuote{random}: return random optimal element in path. #' Default is \dQuote{last}. #' @return [`integer`] #' Index or indices into path. See `ties`. #' @export #' @family optpath #' @examples #' ps = makeParamSet(makeNumericParam("x")) #' op = makeOptPathDF(par.set = ps, y.names = "y", minimize = TRUE) #' addOptPathEl(op, x = list(x = 1), y = 5) #' addOptPathEl(op, x = list(x = 2), y = 3) #' addOptPathEl(op, x = list(x = 3), y = 9) #' addOptPathEl(op, x = list(x = 4), y = 3) #' as.data.frame(op) #' getOptPathBestIndex(op) #' getOptPathBestIndex(op, ties = "first") getOptPathBestIndex = function(op, y.name = op$y.names[1], dob = op$env$dob, eol = op$env$eol, ties = "last") { assertClass(op, "OptPath") assertChoice(y.name, choices = op$y.names) dob = asInteger(dob, any.missing = TRUE) eol = asInteger(eol, any.missing = TRUE) assertChoice(ties, c("all", "first", "last", "random")) life.inds = which(op$env$dob %in% dob & op$env$eol %in% eol) if (length(life.inds) == 0) { stop("No element found which matches dob and eol restrictions!") } y = getOptPathY(op, y.name)[life.inds] if (all(is.na(y))) { best.inds = life.inds } else { if (op$minimize[y.name]) { best.inds = which(min(y, na.rm = TRUE) == y) } else { best.inds = which(max(y, na.rm = TRUE) == y) } best.inds = life.inds[best.inds] } if (length(best.inds) > 1L) { if (ties == "all") { return(best.inds) } else if (ties == "first") { return(best.inds[1]) } else if (ties == "last") { return(best.inds[length(best.inds)]) } else if (ties == "random") { return(best.inds[sample(length(best.inds), 1L)]) } } else { return(best.inds) } } #' Get indices of pareto front of optimization path. #' #' @template arg_op #' @param y.names [character]\cr #' Names of performance measures to construct pareto front for. #' Default is all performance measures. #' @template arg_opgetter_dob #' @template arg_opgetter_eol #' @param index (`logical(1)`)\cr #' Return indices into path of front or y-matrix of nondominated points? #' Default is `FALSE`. #' @return `matrix` | `integer`. Either matrix (with named columns) of points of #' front in objective space or indices into path for front. #' @export #' @family optpath #' @examples #' ps = makeParamSet(makeNumericParam("x")) #' op = makeOptPathDF(par.set = ps, y.names = c("y1", "y2"), minimize = c(TRUE, TRUE)) #' addOptPathEl(op, x = list(x = 1), y = c(5, 3)) #' addOptPathEl(op, x = list(x = 2), y = c(2, 4)) #' addOptPathEl(op, x = list(x = 3), y = c(9, 4)) #' addOptPathEl(op, x = list(x = 4), y = c(4, 9)) #' as.data.frame(op) #' getOptPathParetoFront(op) #' getOptPathParetoFront(op, index = TRUE) getOptPathParetoFront = function(op, y.names = op$y.names, dob = op$env$dob, eol = op$env$eol, index = FALSE) { assertClass(op, "OptPath") assertCharacter(y.names, min.len = 2L) assertSubset(y.names, op$y.names, empty.ok = FALSE) dob = asInteger(dob, any.missing = TRUE) eol = asInteger(eol, any.missing = TRUE) assertFlag(index, na.ok = TRUE) requirePackages("emoa", default.method = "load") life.inds = which(op$env$dob %in% dob & op$env$eol %in% eol) if (length(life.inds) == 0L) { stop("No element found which matches dob and eol restrictions!") } y = getOptPathY(op, y.names, drop = FALSE)[life.inds, , drop = FALSE] # multiply columns with -1 if maximize k = ifelse(op$minimize, 1, -1) y2 = t(y) * k # is_dominated has kind of buggy behavoiur if y2 is a row # (it hinks, we have a 1-dimensional optimization prob und returns the min index) # so we have to treat this case manually if (nrow(y2) == 1L) { nondom = 1L } else { nondom = which(!emoa::is_dominated(y2)) } if (index) { return(life.inds[nondom]) } else { return(y[nondom, , drop = FALSE]) } } ParamHelpers/R/isType.R0000644000176000001440000000432413414125445014474 0ustar ripleyusers#' @title Check parameter / parameter set contain ONLY a certain type. #' #' @description #' An empty param set is considered to be of all types. #' #' @template arg_par_or_set #' @template arg_include_int #' @template arg_include_logical #' @template ret_bool #' @name isType #' @rdname isType NULL #' @export #' @rdname isType isNumeric = function(par, include.int = TRUE) { assert(checkClass(par, "Param"), checkClass(par, "ParamSet")) UseMethod("isNumeric") } #' @export isNumeric.ParamSet = function(par, include.int = TRUE) { all(vlapply(par$pars, isNumeric.Param, include.int = include.int)) } #' @export isNumeric.Param = function(par, include.int = TRUE) { isNumericTypeString(par$type, include.int) } #' @export #' @rdname isType isDiscrete = function(par, include.logical = TRUE) { assert(checkClass(par, "Param"), checkClass(par, "ParamSet")) UseMethod("isDiscrete") } #' @export isDiscrete.ParamSet = function(par, include.logical = TRUE) { hasAllParamsOfTypes(par, getTypeStringsDiscrete(include.logical)) } #' @export isDiscrete.Param = function(par, include.logical = TRUE) { par$type %fin% getTypeStringsDiscrete(include.logical = include.logical) } #' @export #' @rdname isType isInteger = function(par) { assert(checkClass(par, "Param"), checkClass(par, "ParamSet")) UseMethod("isInteger") } #' @export isInteger.ParamSet = function(par) { return(hasAllParamsOfTypes(par, getTypeStringsInteger())) } #' @export isInteger.Param = function(par) { return(par$type %fin% c("integer", "integervector")) } #' @export #' @rdname isType isLogical = function(par) { assert(checkClass(par, "Param"), checkClass(par, "ParamSet")) UseMethod("isLogical") } #' @export isLogical.ParamSet = function(par) { return(hasAllParamsOfTypes(par, getTypeStringsLogical())) } #' @export isLogical.Param = function(par) { return(isLogicalTypeString(par$type)) } #' @export #' @rdname isType isCharacter = function(par) { assert(checkClass(par, "Param"), checkClass(par, "ParamSet")) UseMethod("isCharacter") } #' @export isCharacter.ParamSet = function(par) { return(hasAllParamsOfTypes(par, getTypeStringsCharacter())) } #' @export isCharacter.Param = function(par) { return(isCharacterTypeString(par$type)) } ParamHelpers/R/isVector.R0000644000176000001440000000072313633666270015025 0ustar ripleyusers#' @title Check parameter / parameter set for vector params. #' #' @description #' `TRUE` if the parameter is a vector parameter or all parameters in the #' set are vector parameters. #' #' @template arg_par_or_set #' @return `logical(1)`. #' @export isVector = function(par) { UseMethod("isVector") } #' @export isVector.Param = function(par) { isVectorTypeString(par$type) } #' @export isVector.ParamSet = function(par) { all(vlapply(par$pars, isVector)) } ParamHelpers/R/OptPathDF_as_data_frame.R0000644000176000001440000000640013633666270017644 0ustar ripleyusers#' Convert optimization path to data.frame. #' @description #' The following types of columns are created: #' \tabular{ll}{ #' x-numeric(vector) \tab `numeric` \cr #' x-integer(vector) \tab `integer` \cr #' x-discrete(vector) \tab `factor` (names of values = levels) \cr #' x-logical(vector) \tab `logical` \cr #' y-columns \tab `numeric` \cr #' dob \tab `integer` \cr #' eol \tab `integer` \cr #' error.message \tab `character` \cr #' exec.time \tab `numeric` \cr #' extra-columns \tab any \cr #' } #' If you want to convert these, look at [BBmisc::convertDataFrameCols()]. #' Dependent parameters whose constraints are unsatisfied generate `NA` entries #' in their respective columns. Factor columns of discrete parameters always #' have their complete level set from the `param.set`. #' #' @param x ([OptPath()])\cr #' Optimization path. #' @param row.names [character]\cr #' Row names for result. #' Default is none. #' @param optional (any)\cr #' Currently ignored. #' @param include.x (`logical(1)`)\cr #' Include all input params? #' Default is `TRUE`. #' @param include.y (`logical(1)`)\cr #' Include all y-columns? #' Default is `TRUE`. #' @param include.rest (`logical(1)`)\cr #' Include all other columns? #' Default is `TRUE`. #' @template arg_opgetter_dob #' @template arg_opgetter_eol #' @param ... (any) \cr #' Currently ignored. #' @return [`data.frame`]. #' @export as.data.frame.OptPathDF = function(x, row.names = NULL, optional = FALSE, include.x = TRUE, include.y = TRUE, include.rest = TRUE, dob = x$env$dob, eol = x$env$eol, ...) { assertFlag(include.x) assertFlag(include.y) assertFlag(include.rest) dob = asInteger(dob) eol = asInteger(eol) if (!include.x && !include.y && !include.rest) { stopf("Not able to create data.frame from opt.path. You need to include something!") } ind = getOptPathDobAndEolIndex(x, dob, eol) if (!any(ind)) { stopf("No elements where selected (via 'dob' and 'eol')!") } res = makeDataFrame(nrow = sum(ind), ncol = 0) if (include.x || include.y) { df = x$env$path[ind, , drop = FALSE] y.cols = which(colnames(df) %in% x$y.names) if (include.x) { x.df = df[, -y.cols, drop = FALSE] x.df = fixDesignFactors(x.df, x$par.set) # keeps factor levels res = cbind(res, x.df) } if (include.y) { res = cbind(res, df[, y.cols, drop = FALSE]) } res = convertDataFrameCols(res, chars.as.factor = TRUE) } if (include.rest) { res = cbind(res, dob = x$env$dob[ind], eol = x$env$eol[ind]) # if err message / exec time included, add it if (!is.null(x$env$error.message)) { res$error.message = x$env$error.message[ind] } if (!is.null(x$env$exec.time)) { res$exec.time = x$env$exec.time[ind] } if (!is.null(x$env$extra)) { extra.clean = lapply(x$env$extra[ind], removeDotEntries) res = cbind(res, convertListOfRowsToDataFrame(extra.clean)) } } if (!is.null(row.names)) { assertCharacter(row.names, len = nrow(res), any.missing = FALSE) rownames(res) = row.names } return(res) } # remove all named entries that have a name starting with a dot removeDotEntries = function(l) { l[!startsWith(names(l), ".")] } ParamHelpers/R/hasExpression.R0000644000176000001440000000224413633666270016062 0ustar ripleyusers#' @title Check if parameter values contain expressions. #' #' @description Checks if a parameter, parameter set or list of parameters #' contain expressions. #' @param obj ([Param()] | [ParamHelpers::ParamSet()] | `list`)\cr #' Parameter, parameter set or list of parameters. #' @return `logical(1)`. #' @examples #' ps1 = makeParamSet( #' makeNumericParam("x", lower = 1, upper = 2), #' makeNumericParam("y", lower = 1, upper = 10) #' ) #' #' ps2 = makeParamSet( #' makeNumericLearnerParam("x", lower = 1, upper = 2), #' makeNumericLearnerParam("y", lower = 1, upper = expression(p)) #' ) #' #' hasExpression(ps1) #' hasExpression(ps2) #' @export hasExpression = function(obj) { UseMethod("hasExpression") } #' @export hasExpression.Param = function(obj) { any(vlapply(obj, is.expression)) } #' @export hasExpression.LearnerParam = function(obj) { any(vlapply(obj, is.expression)) } #' @export hasExpression.ParamSet = function(obj) { any(vlapply(obj$pars, hasExpression)) } #' @export hasExpression.LearnerParamSet = function(obj) { any(vlapply(obj$pars, hasExpression)) } #' @export hasExpression.list = function(obj) { any(vlapply(obj, hasExpression)) } ParamHelpers/R/getRequiredParamNames.R0000644000176000001440000000103213633666270017446 0ustar ripleyusers# @description # Returns the names of all params which are required by the given Param or ParamSet. # @template arg_par_or_set # @return [\code{character}]: names of parameters which are required getRequiredParamNames = function(par) { UseMethod("getRequiredParamNames") } getRequiredParamNames.Param = function(par) { all.vars(par$requires) } getRequiredParamNames.ParamSet = function(par) { if (isEmpty(par)) { return(character(0L)) } unique(unlist(lapply(par$pars, getRequiredParamNames.Param), use.names = FALSE)) } ParamHelpers/R/getParamTypes.R0000644000176000001440000000350313633666270016013 0ustar ripleyusers#' Returns type information for a parameter set. #' #' @template arg_parset #' @param df.cols (`logical(1)`)\cr #' If `FALSE` simply return the parameter types in the set, #' i.e., `par$type`. #' If `TRUE`, convert types so they correspond to R types of a data.frame #' where values of this set might be stored. #' This also results in replication of output types for #' vector parameters. #' Default is `FALSE`. #' @param df.discretes.as.factor (`logical(1)`)\cr #' If `df.cols` is `TRUE`: #' Should type for discrete params be `factor` or `character`? #' Default is `TRUE`. #' @param use.names (`logical(1)`)\cr #' Name the result vector? #' Default is `FALSE`. #' @param with.nr (`logical(1)`)\cr #' Should number from 1 to length be appended to name? #' Only used if `use.names` and `df.cols` are `TRUE`. #' Default is `TRUE`. #' @return [`character`]. #' @export getParamTypes = function(par.set, df.cols = FALSE, df.discretes.as.factor = TRUE, use.names = FALSE, with.nr = TRUE) { assertClass(par.set, "ParamSet") assertFlag(df.cols) assertFlag(df.discretes.as.factor) assertFlag(use.names) assertFlag(with.nr) types = extractSubList(par.set$pars, "type") if (length(types) == 0L) { return(character(0L)) } recode = function(types, from, to) { i = fmatch(types, from, nomatch = 0L) types[i > 0L] = to[i] rep(types, getParamLengths(par.set)) } if (df.cols) { to = if (df.discretes.as.factor) { c("numeric", "integer", "factor", "factor", "logical", "character") } else { c("numeric", "integer", "character", "character", "logical", "character") } types = recode(types, ph$convert.param.types.from, to) } ns = if (use.names) { getParamIds(par.set, repeated = df.cols, with.nr = with.nr) } else { NULL } return(setNames(types, ns)) } ParamHelpers/R/ParamSet.R0000644000176000001440000001320413633666270014741 0ustar ripleyusers#' @title Construct a parameter set. #' #' @description #' `makeParamSet`: Construct from a bunch of parameters. #' #' Multiple sets can be concatenated with `c`. #' #' The constructed S3 class is simply a list that contains the element `pars`. #' `pars` is a list of the passed parameters, named by their ids. #' #' If `keys` are provided it will automatically be checked whether all #' expressions within the provided parameters only contain arguments that are a #' subset of keys. #' #' @param ... ([Param()])\cr #' Parameters. #' @param params (list of [Param()])\cr #' List of parameters, alternative way instead of using `...`. #' @param forbidden (`NULL` | R expression)\cr #' States forbidden region of parameter set via an expression. Every setting #' which satisfies this expression is considered to be infeasible. This makes #' it possible to exclude more complex region of the parameter space than #' through simple constraints or `requires`-conditions (although these should #' be always used when possible). If parameters have associated trafos, the #' forbidden region must always be specified on the original scale and not the #' transformed one. Default is `NULL` which means no forbidden region. #' @template arg_keys #' @return [ParamSet()] | `LearnerParamSet`. #' If all parameters of the `ParamSet` are learner parameters, the output #' will inherit the class `LearnerParamSet`. #' @aliases ParamSet #' @export #' @examples #' makeParamSet( #' makeNumericParam("u", lower = 1), #' makeIntegerParam("v", lower = 1, upper = 2), #' makeDiscreteParam("w", values = 1:2), #' makeLogicalParam("x"), #' makeDiscreteVectorParam("y", len = 2, values = c("a", "b")) #' ) #' makeParamSet( #' makeNumericParam("u", lower = expression(ceiling(n))), #' makeIntegerParam("v", lower = expression(floor(n)), upper = 2), #' keys = c("p", "n") #' ) #' makeParamSet( #' makeNumericParam("min", lower = 0, upper = 0.8), #' makeNumericParam("max", lower = 0.2, upper = 1), #' forbidden = expression(min > max) #' ) makeParamSet = function(..., params = NULL, forbidden = NULL, keys = NULL) { pars = list(...) if (length(pars) > 0 && !is.null(params)) { stop("You can only use one of ... or params!") } if (!is.null(params)) { assertList(params, types = "Param") pars = params } else { assertList(pars, types = "Param") } ns = extractSubList(pars, "id") if (anyDuplicated(ns)) { stop("All parameters must have unique names!") } names(pars) = ns par.set = makeS3Obj("ParamSet", pars = pars, forbidden = forbidden) if (length(pars) > 0L) { # if all Params are LearnerParams, then the ParSet is considered # to be a LearnerParSet and we automatically extend the keys by # the default keys from mlr, i.e. task, n, p, k and type if (all(vlapply(pars, inherits, what = "LearnerParam"))) { par.set = addClasses(par.set, classes = "LearnerParamSet") keys = union(keys, c("task", "n", "p", "k", "type")) } if (!is.null(keys) && (hasExpression(par.set))) { checkExpressionFeasibility(par.set = par.set, keys = keys) } } return(par.set) } getParSetPrintData = function(x, trafo = TRUE, used = TRUE, constr.clip = 40L) { d = lapply(x$pars, getParPrintData, trafo = trafo, used = used, constr.clip = constr.clip) return(do.call(rbind, d)) } #' @export print.ParamSet = function(x, ..., trafo = TRUE, used = TRUE, constr.clip = 40L) { if (isEmpty(x)) { print("Empty parameter set.") } else { print(getParSetPrintData(x, trafo = trafo, used = used, constr.clip = constr.clip)) } if (hasForbidden(x)) { catf("Forbidden region specified.") } return(invisible(NULL)) } #' @export c.ParamSet = function(..., recursive = FALSE) { pss = list(...) pars = Reduce(c, lapply(pss, function(ps) ps$pars)) # remove the names here. if 'params' is a par name, this wont work in the # contructor call but we are allowed to pass the list without names, as they # are set again automatically later for pars names(pars) = NULL return(do.call(makeParamSet, pars)) } #' Check whether parameter set is empty. #' #' @param par.set (ParamSet()])\cr #' Parameter set. #' @return `logical(1)`. #' @export isEmpty = function(par.set) { assertClass(par.set, "ParamSet") UseMethod("isEmpty") } #' @export isEmpty.ParamSet = function(par.set) { return(length(par.set$pars) == 0) } #' `makeNumericParamSet`: Convenience function for numerics. #' #' @param id (`character(1)`)\cr #' Name of parameter. #' @param len (`integer(1)`)\cr #' Length of vector. #' @param lower (`numeric`)\cr #' Lower bound. #' Default is `-Inf`. #' @param upper [numeric] \cr #' Upper bound. #' Default is `Inf`. #' @param vector (`logical(1)`) \cr #' Should a `NumericVectorParam` be used instead of #' n `NumericParam` objects? #' Default is `TRUE`. #' @rdname makeParamSet #' @export makeNumericParamSet = function(id = "x", len, lower = -Inf, upper = Inf, vector = TRUE) { assertString(id) if (missing(len)) { if (!missing(lower)) { len = length(lower) } else if (!missing(upper)) { len = length(upper) } } else { len = asInt(len) } if (is.numeric(lower) && length(lower) == 1L) { lower = rep(lower, len) } if (is.numeric(upper) && length(upper) == 1L) { upper = rep(upper, len) } assertNumeric(lower, len = len) assertNumeric(upper, len = len) assertFlag(vector) if (vector) { return(makeParamSet(makeNumericVectorParam(id = id, len = len, lower = lower, upper = upper))) } else { return(makeParamSet(params = lapply(1:len, function(i) { makeNumericParam(id = paste(id, i, sep = ""), lower = lower[i], upper = upper[i]) }) )) } } ParamHelpers/R/isSpecialValue.R0000644000176000001440000000052513633666270016140 0ustar ripleyusers#' @title Is a given value in the list of special values for a param? #' #' @description #' See title. #' #' @template arg_par #' @param x (any) \cr #' Single value to check. #' @return `logical(1)`. #' @export isSpecialValue = function(par, x) { any(vlapply(par$special.vals, function(special.val) isTRUE(all.equal(x, special.val)))) } ParamHelpers/R/makeLearnerParamFuns.R0000644000176000001440000000760013633666270017273 0ustar ripleyusers#' @rdname LearnerParam #' @export makeNumericLearnerParam = function(id, lower = -Inf, upper = Inf, allow.inf = FALSE, default, when = "train", requires = NULL, tunable = TRUE, special.vals = list()) { makeParam(id = id, type = "numeric", learner.param = TRUE, lower = lower, upper = upper, allow.inf = allow.inf, default = default, requires = requires, tunable = tunable, special.vals = special.vals, when = when) } #' @rdname LearnerParam #' @export makeNumericVectorLearnerParam = function(id, len = as.integer(NA), lower = -Inf, upper = Inf, allow.inf = FALSE, default, when = "train", requires = NULL, tunable = TRUE, special.vals = list()) { makeParam(id = id, type = "numericvector", learner.param = TRUE, len = len, lower = lower, upper = upper, allow.inf = allow.inf, default = default, requires = requires, tunable = tunable, special.vals = special.vals, when = when) } #' @rdname LearnerParam #' @export makeIntegerLearnerParam = function(id, lower = -Inf, upper = Inf, default, when = "train", requires = NULL, tunable = TRUE, special.vals = list()) { makeParam(id = id, type = "integer", learner.param = TRUE, lower = lower, upper = upper, default = default, requires = requires, tunable = tunable, special.vals = special.vals, when = when) } #' @rdname LearnerParam #' @export makeIntegerVectorLearnerParam = function(id, len = as.integer(NA), lower = -Inf, upper = Inf, default, when = "train", requires = NULL, tunable = TRUE, special.vals = list()) { makeParam(id = id, type = "integervector", learner.param = TRUE, len = len, lower = lower, upper = upper, default = default, requires = requires, tunable = tunable, special.vals = special.vals, when = when) } #' @rdname LearnerParam #' @export makeDiscreteLearnerParam = function(id, values, default, when = "train", requires = NULL, tunable = TRUE, special.vals = list()) { makeParam(id = id, type = "discrete", learner.param = TRUE, values = values, default = default, requires = requires, tunable = tunable, special.vals = special.vals, when = when) } #' @rdname LearnerParam #' @export makeDiscreteVectorLearnerParam = function(id, len = as.integer(NA), values, default, when = "train", requires = NULL, tunable = TRUE, special.vals = list()) { makeParam(id = id, type = "discretevector", learner.param = TRUE, len = len, values = values, default = default, requires = requires, tunable = tunable, special.vals = special.vals, when = when) } #' @rdname LearnerParam #' @export makeLogicalLearnerParam = function(id, default, when = "train", requires = NULL, tunable = TRUE, special.vals = list()) { values = list("TRUE" = TRUE, "FALSE" = FALSE) makeParam(id = id, type = "logical", learner.param = TRUE, values = values, default = default, requires = requires, tunable = tunable, special.vals = special.vals, when = when) } #' @rdname LearnerParam #' @export makeLogicalVectorLearnerParam = function(id, len = as.integer(NA), default, when = "train", requires = NULL, tunable = TRUE, special.vals = list()) { values = list("TRUE" = TRUE, "FALSE" = FALSE) makeParam(id = id, type = "logicalvector", learner.param = TRUE, len = len, values = values, default = default, requires = requires, tunable = tunable, special.vals = special.vals, when = when) } #' @rdname LearnerParam #' @export makeUntypedLearnerParam = function(id, default, when = "train", requires = NULL, tunable = TRUE, special.vals = list()) { makeParam(id = id, type = "untyped", learner.param = TRUE, default = default, requires = requires, tunable = tunable, special.vals = special.vals, when = when) } #' @rdname LearnerParam #' @export makeFunctionLearnerParam = function(id, default, when = "train", requires = NULL, tunable = TRUE, special.vals = list()) { makeParam(id = id, type = "function", learner.param = TRUE, default = default, requires = requires, tunable = tunable, special.vals = special.vals, when = when) } ParamHelpers/R/dfRowsToList.R0000644000176000001440000000550413633666270015634 0ustar ripleyusers#' @title Convert a data.frame row to list of parameter-value-lists. #' #' @description Please note that (naturally) the columns of `df` have to be of #' the correct type w.r.t. the corresponding parameter. The only exception are #' integer parameters where the corresponding columns in `df` are allowed to be #' numerics. And also see the argument `enforce.col.types` as a way around this #' restriction. #' #' \tabular{ll}{ #' numeric(vector) \tab `numeric` \cr #' integer(vector) \tab `integer` \cr #' discrete(vector) \tab `factor` (names of values = levels) \cr #' logical(vector) \tab `logical` #' } #' #' Dependent parameters whose requirements are not satisfied are represented by #' a scalar NA in the output. #' #' @param df (`data.frame`)\cr #' Data.frame, potentially from [OptPathDF()]. #' Columns are assumed to be in the same order as par.set. #' @template arg_parset #' @param i (`integer(1)`)\cr #' Row index. #' @param enforce.col.types (`logical(1)`)\cr #' Should all `df` columns be initially converted to the type returned by #' `getParamTypes(df, df.cols = TRUE)`. This can help to work with #' \dQuote{non-standard} data.frames where the types are slightly #' \dQuote{off}. But note that there is no guarantee that this will work if #' the types are really wrong and there is no naturally correct way to convert #' them. Default is `FALSE`. #' @param ... (any)\cr #' Arguments passed to [BBmisc::convertDataFrameCols()] #' @return [`list`]. Named by parameter ids. #' @export #' @useDynLib ParamHelpers c_dfRowsToList #' @rdname dfRowsToList dfRowsToList = function(df, par.set, enforce.col.types = FALSE, ...) { assertClass(df, "data.frame") assertClass(par.set, "ParamSet") assertFlag(enforce.col.types) if (enforce.col.types) { types = getParamTypes(par.set, df.cols = TRUE) for (i in seq_along(types)) { tt = types[i] if (tt == "factor") { df[, i] = as.factor(df[, i]) } else { df[, i] = as(df[, i], tt) } } } lens = getParamLengths(par.set) cnames = extractSubList(par.set$pars, "cnames", simplify = FALSE) int.type = convertTypesToCInts(getParamTypes(par.set, df.cols = TRUE)) # factors to chars, so we can evaluate requires df = convertDataFrameCols(df, factors.as.char = TRUE, ...) # ints might just be encoded as nums in df, convert before going to C ints.as.double = mapply(function(type, col) type == 2L && is.double(col), type = int.type, col = df) df[ints.as.double] = lapply(df[ints.as.double], as.integer) .Call("c_dfRowsToList", df, par.set$pars, int.type, names(par.set$pars), lens, cnames, PACKAGE = "ParamHelpers") } #' @export #' @rdname dfRowsToList dfRowToList = function(df, par.set, i, enforce.col.types = FALSE, ...) { dfRowsToList(df = df, par.set = par.set, enforce.col.types = enforce.col.types, ...)[[i]] } ParamHelpers/R/isTypeString.R0000644000176000001440000000224513633666270015674 0ustar ripleyusers#' @title Check if type string is of certain type. #' #' @description `TRUE` iff the type string is a certain type, e.g. #' `isIntegerTypeString` checks if we have \dQuote{integer} or #' \dQuote{integervector}, and `isVectorTypeString` check if we have #' \dQuote{*vector}. #' #' @template arg_typestring #' @template arg_include_int #' @template arg_include_logical #' @template ret_bool #' @name isTypeString #' @rdname isTypeString NULL #' @export #' @rdname isTypeString isNumericTypeString = function(type, include.int = TRUE) { type %fin% getTypeStringsNumeric(include.int) } #' @export #' @rdname isTypeString isIntegerTypeString = function(type) { type %fin% getTypeStringsInteger() } #' @export #' @rdname isTypeString isCharacterTypeString = function(type) { type %fin% getTypeStringsCharacter() } #' @export #' @rdname isTypeString isDiscreteTypeString = function(type, include.logical = TRUE) { type %fin% getTypeStringsDiscrete(include.logical) } #' @export #' @rdname isTypeString isLogicalTypeString = function(type) { type %fin% getTypeStringsLogical() } #' @export #' @rdname isTypeString isVectorTypeString = function(type) { endsWith(type, "vector") } ParamHelpers/R/getBounds.R0000644000176000001440000001313113633666270015156 0ustar ripleyusers#' @title Get lower / upper bounds and allowed discrete values for parameters. #' #' @description `getLower` and `getUpper` return a numerical vector of lower and #' upper bounds, `getValues` returns a list of possible value sets for discrete #' parameters. #' #' Parameters for which such bound make no sense - due to their type - are not #' present in the result. #' #' @param obj ([Param()] | [ParamSet()] | `list`)\cr #' Parameter, parameter set or list of parameters, whose boundaries and/or #' values should be extracted. In case the boundaries or values contain #' expressions, they will be evaluated using the provided dictionary `dict`. #' @param with.nr (`logical(1)`)\cr #' Should number from 1 to length be appended to names of vector params? #' Default is `FALSE`. #' @template arg_dict #' @return `vector` | `list`. Named by parameter ids. #' @export #' @examples #' ps = makeParamSet( #' makeNumericParam("u"), #' makeDiscreteParam("v", values = c("a", "b")), #' makeIntegerParam("w", lower = expression(ceiling(p / 3)), upper = 2), #' makeDiscreteParam("x", values = 1:2), #' makeNumericVectorParam("y", len = 2, lower = c(0, 10), upper = c(1, 11)), #' keys = "p" #' ) #' getLower(ps, dict = list(p = 7)) #' getUpper(ps) #' #' ps = makeParamSet( #' makeNumericParam("u"), #' makeDiscreteParam("w", values = list(a = list(), b = NULL)) #' ) #' getValues(ps) #' #' par.vals = list( #' u = makeNumericParam("u"), #' v = makeIntegerParam("v", lower = 1, upper = 2), #' w = makeDiscreteParam("w", values = 1:2), #' x = makeNumericVectorParam("x", len = 2, lower = c(3, 1), upper = expression(n)) #' ) #' getLower(par.vals) #' getUpper(par.vals, dict = list(n = 12)) getLower = function(obj, with.nr = FALSE, dict = NULL) { getBounds(obj, type.of.bounds = "lower", with.nr = with.nr, dict = dict) } #' @export #' @rdname getLower getUpper = function(obj, with.nr = FALSE, dict = NULL) { getBounds(obj, type.of.bounds = "upper", with.nr = with.nr, dict = dict) } #' @export #' @rdname getLower getValues = function(obj, dict = NULL) { UseMethod("getValues") } #' @export getValues.Param = function(obj, dict = NULL) { assertClass(obj, "Param") assertList(dict, names = "unique", null.ok = TRUE) # values are only possible for params of the types above if (!isDiscrete(obj)) { return(NULL) } # error if dict is not defined, but values contains expression if (is.null(dict) && hasExpression(obj)) { stop("You need to provide a dictionary to get the values.") } eval(obj$values, envir = dict) } #' @export getValues.ParamSet = function(obj, dict = NULL) { assertClass(obj, "ParamSet") assertList(dict, names = "unique", null.ok = TRUE) types = getParamTypes(obj) is.disc = types %fin% getTypeStringsDiscrete() # only consider params with one of the types from above if (!any(is.disc)) { return(list()) } # error if dict is not defined, but at least one value contains an expression if (missing(dict) && any(vlapply(obj$pars[is.disc], hasExpression))) { stop("You need to provide a dictionary to get the values.") } lapply(obj$pars[is.disc], function(p) eval(p$values, envir = dict)) } #' @export getValues.list = function(obj, dict = NULL) { assertClass(obj, "list") assertList(dict, names = "unique", null.ok = TRUE) # create a pseudo-ParamSet and use of getValues.ParamSet par.set = list(pars = obj) class(par.set) = "ParamSet" values = getValues(obj = par.set, dict = dict) return(values) } getBounds = function(obj, type.of.bounds, with.nr = FALSE, dict = NULL) { UseMethod("getBounds") } # workhorse for getLower and getUpper (for Param) getBounds.Param = function(obj, type.of.bounds, with.nr = FALSE, dict = NULL) { assertClass(obj, "Param") assertList(dict, names = "unique", null.ok = TRUE) # if the Param is non-numeric, return NULL if (!(obj$type %fin% getTypeStringsNumeric())) { return(NULL) } # filter to numerics, and get bounds, flat-join them and name them bound = obj[[type.of.bounds]] # if the bound is an expression, it needs to be evaluated first if (is.expression(bound)) { if (is.null(dict)) { stop("You need to provide a dictionary to get the bounds.") } bound = eval(bound, envir = dict) } # assure that the length of the bound corresponds to the pre-defined length len = obj$len if (length(bound) == 1L && !is.na(len) && len > 1L) { bound = rep(bound, len) } setNames(bound, getParamIds(obj, repeated = TRUE, with.nr = with.nr)) } # workhorse for getLower and getUpper for ParamSet getBounds.ParamSet = function(obj, type.of.bounds, with.nr = FALSE, dict = NULL) { assertClass(obj, "ParamSet") assertList(dict, names = "unique", null.ok = TRUE) # if we don't have numerics, return empty vector if (!hasNumeric(obj, include.int = TRUE)) { return(numeric(0L)) } # filter to numerics psnum = filterParamsNumeric(obj, include.int = TRUE) # get bounds of all numeric Params, flat-join and name them bounds = lapply(psnum$pars, function(p) { getBounds(obj = p, type.of.bounds = type.of.bounds, with.nr = with.nr, dict = dict) }) setNames(unlist(bounds), getParamIds(psnum, repeated = TRUE, with.nr = with.nr)) } # workhorse for of getLower and getUpper for regular lists getBounds.list = function(obj, type.of.bounds, with.nr = FALSE, dict = NULL) { assertClass(obj, "list") assertList(dict, names = "unique", null.ok = TRUE) # create a pseudo-ParamSet and make use of the existing functions par.set = list(pars = obj) class(par.set) = "ParamSet" bounds = getBounds(obj = par.set, type.of.bounds = type.of.bounds, with.nr = with.nr, dict = dict) return(bounds) } ParamHelpers/R/aParam.R0000644000176000001440000002526613633666270014441 0ustar ripleyusers#' @title Create a description object for a parameter. #' #' @description For each parameter type a special constructor function is #' available, see below. #' #' For the following arguments you can also pass an `expression` instead of a #' concrete value: `default`, `len`, `lower`, `upper`, `values`. These #' expressions can depend on arbitrary symbols, which are later filled in / #' substituted from a dictionary, in order to produce a concrete valu, see #' [evaluateParamExpressions()]. So this enables data / context dependent #' settings, which is sometimes useful. #' #' The S3 class is a list which stores these elements: #' \describe{ #' \item{id (`character(1)`)}{See argument of same name.} #' \item{type (`character(1)`)}{Data type of parameter. For all type string see (getTypeStringsAll())} #' \item{len (`integer(1)` | `expression`)}{See argument of same name.} #' \item{lower (`numeric` | `expression`)}{See argument of same name. Length of this vector is `len`.} #' \item{upper (`numeric` | `expression`)}{See argument of same name. Length of this vector is `len`.} #' \item{values (`list` | `expression`)}{Discrete values, always stored as a named list.} #' \item{cnames (`character`}{See argument of same name.} #' \item{allow.inf (`logical(1)`)}{See argument of same name.} #' \item{trafo (`NULL` | `function(x)`)}{See argument of same name.} #' \item{requires (`NULL` | `expression`)}{See argument of same name.} #' \item{default (any concrete value | `expression`)}{See argument of same name.} #' \item{has.default (`logical(1)`)}{Extra flag to really be able to check whether the user passed a default, to avoid troubles with `NULL` and `NA`.} #' \item{tunable (`logical(1)`)}{See argument of same name.} #' \item{special.vals (`list`)}{See argument of same name.} #' } #' #' @param id (`character(1)`)\cr #' Name of parameter. #' @param len (`integer(1)` | `expression`)\cr #' Length of vector parameter. #' @param lower (`numeric` | `expression`)\cr #' Lower bounds. A singe value of #' length 1 is automatically replicated to `len` for vector parameters. If #' `len = NA` you can only pass length-1 scalars. Default is `-Inf`. #' @param upper (`numeric` | `expression`)\cr #' Upper bounds. A singe value of #' length 1 is automatically replicated to `len` for vector parameters. If #' `len = NA` you can only pass length-1 scalars. Default is `Inf`. #' @param values (`vector` | `list` | `expression`)\cr #' Possible discrete values. #' Instead of using a vector of atomic values, you are also allowed to pass a #' list of quite \dQuote{complex} R objects, which are used as discrete #' choices. If you do the latter, the elements must be uniquely named, so that #' the names can be used as internal representations for the choice. #' @param cnames (`character`)\cr #' Component names for vector params (except #' discrete). Every function in this package that creates vector values for #' such a param, will name that vector with `cnames`. #' @param allow.inf (`logical(1)`)\cr #' Allow infinite values for numeric and #' numericvector params to be feasible settings. Default is `FALSE`. #' @param default (any concrete value | `expression`)\cr #' Default value used in #' learner. Note: When this is a discrete parameter make sure to use a VALUE #' here, not the NAME of the value. If this argument is missing, it means no #' default value is available. #' @param trafo (`NULL` | `function(x)`)\cr #' Function to transform parameter. It #' should be applied to the parameter value before it is, e.g., passed to a #' corresponding objective function. Function must accept a parameter value as #' the first argument and return a transformed one. Default is `NULL` which #' means no transformation. #' @param requires (`NULL` | `call` | `expression`)\cr #' States requirements on #' other parameters' values, so that setting this parameter only makes sense #' if its requirements are satisfied (dependent parameter). Can be an object #' created either with `expression` or `quote`, the former type is #' auto-converted into the later. Only really useful if the parameter is #' included in a (ParamSet()). Default is `NULL` which means no requirements. #' @param tunable (`logical(1)`)\cr #' Is this parameter tunable? Defining a #' parameter to be not-tunable allows to mark arguments like, e.g., #' \dQuote{verbose} or other purely technical stuff. Note that this flag is #' most likely not respected by optimizing procedures unless stated otherwise. #' Default is `TRUE` (except for `untyped`, `function`, `character` and #' `characterVector`) which means it is tunable. #' @param special.vals (`list()`)\cr #' A list of special values the parameter can #' except which are outside of the defined range. Default is an empty list. #' @return [[Param()]]. #' @name Param #' @rdname Param #' @examples #' makeNumericParam("x", lower = -1, upper = 1) #' makeNumericVectorParam("x", len = 2) #' makeDiscreteParam("y", values = c("a", "b")) #' makeCharacterParam("z") NULL makeParam = function(id, type, learner.param, len = 1L, lower = NULL, upper = NULL, values = NULL, cnames = NULL, allow.inf = FALSE, default, trafo = NULL, requires = NULL, tunable = TRUE, special.vals = list(), when) { assertString(id) assert( checkCount(len, na.ok = learner.param), checkClass(len, "expression") ) if (isNumericTypeString(type, include.int = TRUE)) { assert( checkNumeric(lower, any.missing = FALSE), checkClass(lower, "expression") ) assert( checkNumeric(upper, any.missing = FALSE), checkClass(upper, "expression") ) # the following check also ensures that if len=NA, the lower and upper must be scalars if (!is.expression(len) && !is.expression(lower)) { if (length(lower) %nin% c(1L, len)) { stopf("For param '%s' length 'lower' must be either 1 or length of param, not: %i", id, length(lower)) } } if (!is.expression(len) && !is.expression(upper)) { if (length(upper) %nin% c(1L, len)) { stopf("For param '%s' length 'upper' must be either 1 or length of param, not: %i", id, length(upper)) } } } if (isDiscreteTypeString(type)) { values = checkValuesForDiscreteParam(id, values) } # We cannot check default} for NULL or NA as this could be the default value! if (missing(default)) { has.default = FALSE default = NULL } else { has.default = TRUE } if (!is.null(trafo)) { assertFunction(trafo) } if (!is.null(requires)) { requires = convertExpressionToCall(requires) assertSubset(mode(requires), c("call", "name")) } assertList(special.vals) if (isNumericTypeString(type, include.int = TRUE)) { if (!is.expression(len) && !is.na(len) && len > 1L) { if (isScalarNumeric(lower)) { lower = rep(lower, len) } if (isScalarNumeric(upper)) { upper = rep(upper, len) } } if (!is.expression(lower) && !is.expression(upper)) { if (any(upper < lower)) { stopf("For param '%s' some component of 'upper' is smaller than the corresponding one in 'lower'", id) } } } p = makeS3Obj("Param", id = id, type = type, len = len, lower = lower, upper = upper, values = values, cnames = cnames, allow.inf = allow.inf, has.default = has.default, default = default, trafo = trafo, requires = requires, tunable = tunable, special.vals = special.vals ) if (learner.param) { p = makeLearnerParam(p, when) } if (has.default && !is.expression(default)) { if (!isFeasible(p, default)) { stop(p$id, " : 'default' must be a feasible parameter setting.") } } return(p) } getParPrintData = function(x, trafo = TRUE, used = TRUE, constr.clip = 40L) { g = function(n) collapse(sprintf("%.3g", n)) if (isNumeric(x, include.int = TRUE)) { if (!is.expression(x$lower) && !is.expression(x$upper) && (length(unique(x$lower)) == 1L) && (length(unique(x$upper)) == 1L)) { x$lower = unique(x$lower) x$upper = unique(x$upper) } low = if (is.expression(x$lower)) as.character(x$lower) else g(x$lower) upp = if (is.expression(x$upper)) as.character(x$upper) else g(x$upper) constr = sprintf("%s to %s", low, upp) } else if (isDiscrete(x, include.logical = FALSE)) { vals = if (is.expression(x$values)) as.character(x$values) else collapse(names(x$values)) constr = clipString(vals, constr.clip) } else { constr = "-" } if (x$has.default) { if (!is.expression(x$default)) { def = x$default def = paramValueToString(x, def) } else { def = as.character(x$default) } } else { def = "-" } if (isVector(x)) { if (!is.expression(x$len)) { len = x$len } else { len = as.character(x$len) } } else { len = "-" } d = data.frame( Type = x$type, len = len, Def = def, Constr = constr, Req = ifelse(is.null(x$requires), "-", "Y"), Tunable = x$tunable, stringsAsFactors = FALSE ) if (trafo) { d$Trafo = ifelse(is.null(x$trafo), "-", "Y") } return(d) } #' @export print.Param = function(x, ..., trafo = TRUE) { print(getParPrintData(x, trafo = trafo)) } # helper function to perform sanity checks on values of disctrete param checkValuesForDiscreteParam = function(id, values) { if (is.vector(values) && !is.expression(values)) { values = as.list(values) } assert( checkList(values), checkClass(values, "expression") ) if (!is.expression(values)) { if (length(values) == 0L) { stopf("No possible value for discrete parameter %s!", id) } # check that NA does not occur in values, we use that for "missing state" for dependent params # make sure that this works for complex object too, cannot be done with simple is.na if (any(vlapply(values, isScalarNA))) { stopf("NA is not allowed as a value for discrete parameter %s.\nParamHelpers uses NA as a special value for dependent parameters.", id) } n = length(values) ns = names(values) # if names missing, set all to "" if (is.null(ns)) { ns = rep("", n) } # guess missing names for (i in seq_len(n)) { v = values[[i]] if (is.na(ns[i]) || ns[i] == "") { if (is.character(v) || is.numeric(v)) { ns[i] = as.character(v) } } } names(values) = ns if (!isProperlyNamed(values)) { stopf("Not all values for parameter '%s' were named and names could not be guessed!", id) } # check that NA does not occur in value names, see above if ("NA" %in% names(values)) { stopf("NA is not allowed as a value name for discrete parameter %s.\nParamHelpers uses NA as a special value for dependent parameters.", id) } } return(values) } ParamHelpers/R/renderOptPathPlot_workers.R0000644000176000001440000003146114257525307020422 0ustar ripleyusers# Plot methods for renderOptPathPlot. Nearly the same interface for all plot functions # Not all functions do have all arguments. # @param op # The optimization path # @param .alpha [\code{numeric}]\cr # Vector of alpha values for the points in the plots. # @param .type [\code{factor}]\cr # Vector of types of the points, factor levels are init, seq, prob and marked. # @param dob [\code{numeric}]\cr # Vector of dobs # @param log[\code{character}]\cr # Vector of variables to be logarithmized # @param names [\code{character}]\cr # Vector of the names of the variables. Used to identify variables for the plot. # @param short.names [\code{character}]\cr # Vector of the short names of the variables. This names will be printed in the plot. # Must be the same length as names # @param space[\code{character}] # If the X-Space is plotted, space = "x", if the Y-Space is plotted, space = "y". # Special case 1D -> 1D also "both" is possible. # @param iter [\code{integer(1)}]\cr # Current iteration. # @param classes [\code{character(2)}]\cr # Classes of the variables (numeric or factor) in 2D plots. # @param xlim, ylim [\code{numeric(2)}]\cr # Limits for the x and y axis respectively. # @param colours [\code{character(4)}]\cr # Colours of the points/lines for the three point types init, seq, prob and marked. # @param size [\code{numeric(1)} | NULL]\cr # Size of points / lines. # @return A ggplot object. # Plot method for a one-dimensional numeric X- or Y-Space # Here we use geom_density and geom_rug # And we know both names and short.names have length 1 plot1DNum = function(op, .alpha, .type, log, names, short.names, space, iter, xlim, colours, ggplot.theme) { op$.alpha = .alpha op$.type = .type if (space == "x") { title = ggplot2::ggtitle("X-Space") } if (space == "y") { title = ggplot2::ggtitle("Y-Space") } pl = ggplot2::ggplot(op, ggplot2::aes_string(x = names)) pl = pl + ggplot2::geom_density(colour = "black") pl = pl + title pl = pl + ggplot2::xlab(short.names) pl = pl + ggplot2::geom_rug(ggplot2::aes_string(alpha = ".alpha", colour = ".type"), sides = "b", size = 2L, data = op) if (names %in% log) { pl = pl + ggplot2::coord_trans(xtrans = "log10", limx = xlim) } else { pl = pl + ggplot2::coord_cartesian(xlim = xlim) } pl = pl + ggplot2::guides(alpha = FALSE) pl = pl + ggplot2::scale_alpha_continuous(range = c(max(1 / (iter + 1), 0.1), 1L)) pl = pl + ggplot2::scale_colour_manual(name = "type", values = c(init = colours[1L], seq = colours[2L], prop = colours[3L], marked = colours[4L])) pl = pl + ggplot.theme return(pl) } # Plot method for a one-dimensional discrete X- or Y-Space # Here we use geom_bar plot1DDisc = function(op, .alpha, .type, log, names, short.names, space, iter, ylim, colours, ggplot.theme) { op$.alpha = as.factor(.alpha) op$.type = .type if (space == "x") { title = ggplot2::ggtitle("X-Space") } if (space == "y") { title = ggplot2::ggtitle("Y-Space") } pl = ggplot2::ggplot(op, ggplot2::aes_string(x = names[1L], fill = ".type", alpha = ".alpha")) pl = pl + ggplot2::geom_bar() pl = pl + title pl = pl + ggplot2::xlab(short.names) pl = pl + ggplot2::ylim(ylim) pl = pl + ggplot2::scale_alpha_discrete(range = c(max(1 / (iter + 1), 0.1), 1L)) pl = pl + ggplot2::scale_fill_manual(name = "type", values = c(init = colours[1L], seq = colours[2L], prop = colours[3L], marked = colours[4L])) pl = pl + ggplot.theme pl = pl + ggplot2::guides(alpha = FALSE) return(pl) } # Plot method for a two-dimensional X- or Y-Space # We use geom_point and jitter for discrete variables # y.name: we can plot contour-lines for a singel y-variable if both x-variables # are numeric. in this case, op.y is the data.frame containing the y.variable plot2D = function(op, .alpha, .type, log, names, short.names, y.name = NULL, op.y = NULL, space, iter, classes, xlim, ylim, colours, size, ggplot.theme) { op$.alpha = .alpha op$.type = .type if (space == "x") { title = ggplot2::ggtitle("X-Space") } if (space == "y") { title = ggplot2::ggtitle("Y-Space") } if (space == "both") { title = ggplot2::ggtitle("X- and Y-Space") } factor.classes = classes == "factor" if (any(factor.classes)) { # Jitter only in the discrete directions pos = ggplot2::position_jitter(w = 0.1 * factor.classes[1], h = 0.1 * factor.classes[2]) } else { pos = "identity" } # prepare contour plot if (!is.null(y.name)) { requirePackages(c("interp", "reshape2"), why = "renderOptPathPlot plot2D") fld = with(cbind(op, op.y), interp::interp(x = get(names[1L]), y = get(names[2L]), z = get(y.name))) df = reshape2::melt(fld$z, na.rm = TRUE) names(df) = c(names, y.name) df[[names[1L]]] = fld$x[df[[names[1L]]]] df[[names[2L]]] = fld$y[df[[names[2L]]]] } pl = ggplot2::ggplot() pl = pl + ggplot2::geom_point(data = op, ggplot2::aes_string(x = names[1L], y = names[2L], shape = ".type", colour = ".type", alpha = ".alpha"), size = size, position = pos) # add contour if (!is.null(y.name)) { pl = pl + ggplot2::stat_contour(ggplot2::aes_string(x = names[1L], y = names[2L], z = y.name), data = df) } pl = pl + title pl = pl + ggplot2::xlab(short.names[1L]) + ggplot2::ylab(short.names[2L]) pl = pl + ggplot2::guides(alpha = FALSE) pl = pl + ggplot2::scale_colour_manual(name = "type", values = c(init = colours[1L], seq = colours[2L], prop = colours[3L], marked = colours[4L])) pl = pl + ggplot2::scale_shape_manual(name = "type", values = c(init = 15L, seq = 16L, prop = 17L, marked = 18L)) pl = pl + ggplot2::scale_alpha_continuous(range = c(max(1 / (iter + 1), 0.1), 1L)) pl = pl + ggplot.theme if (classes[1L] == "numeric") { if (names[1L] %in% log) { pl = pl + ggplot2::scale_x_log10(limits = xlim) } else { pl = pl + ggplot2::xlim(xlim) } } if (classes[2L] == "numeric") { if (names[2L] %in% log) { pl = pl + ggplot2::scale_y_log10(limits = ylim) } else { pl = pl + ggplot2::ylim(ylim) } } return(pl) } # Plot method for a multi-dimensional X- or Y-Space # Here we make a PCP using GGally::ggparcoord plotMultiD = function(op, .alpha, .type, log, names, short.names, space, iter, colours, size, scale, ggplot.theme) { args = list(columns = seq_along(names)) # make every variable numeric and check for a log trafo for (var in names) { op[, var] = as.numeric(op[, var]) if (var %in% log) { op[, var] = log10(op[, var]) } } op$.alpha = .alpha # minimal alpha value: op$.type = .type args$data = op args$alphaLines = ".alpha" args$groupColumn = ncol(op) args$scale = scale args$mapping = ggplot2::aes_q(lwd = size) if (space == "x") { title = ggplot2::ggtitle("X-Space") } else { title = ggplot2::ggtitle("Y-Space") } pl = do.call(GGally::ggparcoord, args) pl = pl + ggplot2::ylab("scaled values") pl = pl + ggplot2::scale_x_discrete(labels = short.names) pl = pl + title pl = pl + ggplot2::guides(alpha = FALSE, size = FALSE) pl = pl + ggplot2::scale_colour_manual(name = "type", values = c(init = colours[1L], seq = colours[2L], prop = colours[3L], marked = colours[4L])) pl = pl + ggplot.theme return(pl) } # Function to plot one or more numeric variables over time # names: all corresponding variables must be numeric # short.names: short names of the variables given by names multiVariablesOverTime = function(op, .alpha, dob, log, names, short.names, space, iter, colours, ggplot.theme) { # For rest variables, we can get a NA data.frame here. In this case, no plot if (all(is.na(op[, names]))) { return(NULL) } # allow only log trafo of all variables in this plot log.var = names %in% log if (any(log.var) && !all(log.var)) { stop("If you want to apply a log trafo in an over.time.plot, you have to apply it to every variable.") } for (var in names) { if (!is.numeric(op[, var])) { warning(paste("Converting variable ", var, "to numeric for over time plot.")) } op[, var] = as.numeric(op[, var]) } op2 = op[, names] op2$dob = dob op2$.alpha = .alpha # mean over dob op2 = aggregate(op2, list(op2$dob), mean)[, -1] # reshape into long format op2 = reshape(op2, ids = row.names(op2), times = names, timevar = "variable", varying = list(names), direction = "long", v.names = c("value")) pl = ggplot2::ggplot(op2, ggplot2::aes_string(x = "dob", y = "value", group = "variable", linetype = "variable")) pl = pl + ggplot2::geom_point() pl = pl + ggplot2::geom_line() pl = pl + ggplot2::scale_linetype_discrete(labels = short.names) # For the x axis: only whole numbers as breaks pl = pl + ggplot2::scale_x_continuous(breaks = function(x) pretty(x, n = min(5, iter + 1))) # fixed number of decimals: fmt <- function() { function(x) format(x, nsmall = 3, scientific = FALSE) } if (all(log.var)) { pl = pl + ggplot2::scale_y_log10(labels = fmt()) } else { pl = pl + ggplot2::scale_y_continuous(labels = fmt()) } pl = pl + ggplot.theme return(pl) } # Plots One variable versus the DOB. name is the name of the variable to be plotted oneVariableOverTime = function(op, .alpha, .type, dob, log, names, short.names, iter, size.points, size.lines, colours, ggplot.theme) { # For rest variables, we can get a NA data.frame here. In this case, no plot if (all(is.na(op[, names]))) { return(NULL) } # convert factor variables to numeric if (!is.numeric(op[, names])) { warning(paste("Converting variable ", names, "to numeric for over time plot.")) } op[, names] = as.numeric(op[, names]) # Some data preproc. 2 Different datasets - one for init design, one for rest op = cbind(op, dob = dob, .alpha = .alpha, .type = .type) init.des.inds = dob == 0 op.init.des = op[init.des.inds, , drop = FALSE] op.seq.opt = op[!init.des.inds, , drop = FALSE] # if we want to log and all values are negative, make them positive. # this is special treatment for our ei. if (names %in% log && all(na.omit(op[, names] <= 0))) { op.init.des[, names] = -op.init.des[, names] op.seq.opt[, names] = -op.seq.opt[, names] } aes.points = ggplot2::aes_string(x = "dob", y = names, shape = ".type", colour = ".type", alpha = ".alpha") pl = ggplot2::ggplot(op, ggplot2::aes_string(x = "dob", y = names)) # add initial design points allays with jitter in x-direction, # if discrete also with jitter in y-direction if (length(na.omit(op.init.des[, names])) > 0L) { if (is.numeric(op[, names])) { pl = pl + ggplot2::geom_point(data = op.init.des, mapping = aes.points, size = size.points, position = ggplot2::position_jitter(height = 0.1)) } else { pl = pl + ggplot2::geom_point(data = op.init.des, mapping = aes.points, size = size.points, position = ggplot2::position_jitter(height = 0.1, width = 0.1)) } } # add sequential points, if discrete with jitter in y-direction # Add jitter for discrete variable if (length(na.omit(op.seq.opt[, names])) > 0L) { if (is.numeric(op[, names])) { pl = pl + ggplot2::geom_point(data = op.seq.opt, mapping = aes.points, size = size.points) } else { pl = pl + ggplot2::geom_point(data = op.seq.opt, mapping = aes.points, size = size.points, position = ggplot2::position_jitter(height = 0.1, width = 0.1)) } # mean data for line plot for sequential data - only for numeric vars # Also ylims are only useful for numeric vars if (is.numeric(op[, names])) { op.seq.means = op.seq.opt[!duplicated(op.seq.opt$dob), ] op.seq.means[, names] = tapply(op.seq.opt[, names], op.seq.opt[, "dob"], mean) pl = pl + ggplot2::geom_line(data = op.seq.means, ggplot2::aes_string(x = "dob", y = names), alpha = 0.3) } } # fixed number of decimals: fmt <- function() { function(x) format(x, nsmall = 3, scientific = FALSE) } if (names %in% log) { pl = pl + ggplot2::scale_y_log10(labels = fmt()) } else { pl = pl + ggplot2::scale_y_continuous(labels = fmt()) } pl = pl + ggplot2::geom_vline(xintercept = 0.5) pl = pl + ggplot2::guides(alpha = FALSE) pl = pl + ggplot2::ylab(short.names) pl = pl + ggplot2::scale_colour_manual(name = "type", values = c(init = colours[1L], seq = colours[2L], prop = colours[3L], marked = colours[4L])) pl = pl + ggplot2::scale_shape_manual(name = "type", values = c(init = 15L, seq = 16L, prop = 17L, marked = 18L)) # set range for alpha scale, so that extra variables (that may not exist in # iteration 0) will have the same alpha values as all other variables. range = c(max(min(op$.alpha[!is.na(op[, names])]), 0.1), 1L) pl = pl + ggplot2::scale_alpha_continuous(range = range) # For the x axis: only whole numbers as breaks pl = pl + ggplot2::scale_x_continuous(limits = c(-0.5, NA_real_), breaks = function(x) pretty(x, n = min(5, iter + 1))) pl = pl + ggplot.theme return(pl) } ParamHelpers/R/checkParamSet.R0000644000176000001440000000730613633666270015745 0ustar ripleyusers#' @title Sanity check expressions of a parameter set. #' #' @description #' Checks whether the default values of the numerical parameters are located #' within the corresponding boundaries. In case of discrete parameters it #' checks whether the values are a subset of the parameter's possible values. #' #' @template arg_parset #' @template arg_dict #' @return [`TRUE`] on success. An exception is raised otherwise. #' @export #' @examples #' ps = makeParamSet( #' makeNumericParam("u", lower = expression(p)), #' makeIntegerParam("v", lower = 1, upper = expression(3 * p)), #' makeDiscreteParam("w", default = expression(z), values = c("a", "b")), #' makeDiscreteParam("x", default = "a", values = c("a", "b")), #' keys = c("p", "z") #' ) #' checkParamSet(ps, dict = list(p = 3, z = "b")) checkParamSet = function(par.set, dict = NULL) { assertClass(par.set, "ParamSet") assertList(dict, names = "unique", null.ok = TRUE) # evaluate expressions of par.set (in case it contains any) if (hasExpression(par.set)) { if (is.null(dict)) { # error if dict is not defined, but par.set contains expressions stop("At least one of the parameters contains expressions and therefore 'dict' has to be defined.") } par.set = evaluateParamExpressions(obj = par.set, dict = dict) } # extract bounds, default and values (dict = NULL is sufficient) because # the par.set is already evaluated lower = getLower(par.set, dict = NULL) upper = getUpper(par.set, dict = NULL) default = getDefaults(par.set, dict = NULL) values = getValues(par.set, dict = NULL) # check if defaults are outside the bounds failed.boundary.check = which(vlapply(seq_along(lower), function(i) { id = names(lower)[i] any(lower[[id]] > default[[id]]) || any(upper[[id]] < default[[id]]) })) if (length(failed.boundary.check) > 0L) { stopf("The following %s failed the boundary check: %s", ifelse(length(failed.boundary.check) > 1L, "parameters", "parameter"), paste(names(failed.boundary.check), collapse = ", ")) } # check if defaults are outside the feasible values failed.value.check = which(vlapply(seq_along(default), function(i) { id = names(default)[i] !is.null(values[[id]]) && !is.null(default[[id]]) && !(default[[id]] %in% values[[id]]) })) if (length(failed.value.check) > 0L) { stopf("The following %s 'defaults' that are not part of the possible 'values': %s", ifelse(length(failed.boundary.check) > 1L, "parameters have", "parameter has"), paste(names(failed.boundary.check), collapse = ", ")) } return(TRUE) } # check whether the expressions of a param set are feasible # (internal function which is called in case 'keys' are provided # at the construction of the par.set) checkExpressionFeasibility = function(par.set, keys) { has.expression = vlapply(par.set$pars, hasExpression) # if par.set has no expressions, the expressions are feasible if (!any(has.expression)) { return(TRUE) } # for all params which have an expression, check whether its # arguments are listed in 'keys' lapply(par.set$pars[has.expression], function(par) { # extract all parameter arguments that have expressions expressions = par[vlapply(par, is.expression)] lapply(expressions, function(expr) { # arguments from expression that are not defined in keys missing.vars = all.vars(expr)[all.vars(expr) %nin% keys] if (length(missing.vars) > 0L) { message = sprintf("The %s '%s' %s to be defined in 'keys'", ifelse(length(missing.vars) == 1L, "parameter", "parameters"), paste(missing.vars, collapse = "', '"), ifelse(length(missing.vars) == 1L, "needs", "need")) stop(message) } }) }) return(TRUE) } ParamHelpers/R/removeMissingValues.R0000644000176000001440000000033513633666270017235 0ustar ripleyusers#' Removes all scalar NAs from a parameter setting list. #' #' @param x [list]\cr #' List of parameter values. #' @return [list]. #' @export removeMissingValues = function(x) { return(Filter(Negate(isScalarNA), x)) } ParamHelpers/R/sample.R0000644000176000001440000001014313633666270014505 0ustar ripleyusers#' @title Sample a random value from a parameter or a parameter set uniformly. #' #' @template desc_dep_pars_na #' #' @template arg_par_or_set #' @template arg_disc_names #' @template arg_trafo #' @return The return type is determined by the type of the parameter. For a set #' a named list of such values in the correct order is returned. #' @export #' @examples #' # bounds are necessary here, can't sample with Inf bounds: #' u = makeNumericParam("x", lower = 0, upper = 1) #' # returns a random number between 0 and 1: #' sampleValue(u) #' #' p = makeDiscreteParam("x", values = c("a", "b", "c")) #' # can be either "a", "b" or "c" #' sampleValue(p) #' #' p = makeIntegerVectorParam("x", len = 2, lower = 1, upper = 5) #' # vector of two random integers between 1 and 5: #' sampleValue(p) #' #' ps = makeParamSet( #' makeNumericParam("x", lower = 1, upper = 10), #' makeIntegerParam("y", lower = 1, upper = 10), #' makeDiscreteParam("z", values = 1:2) #' ) #' sampleValue(ps) sampleValue = function(par, discrete.names = FALSE, trafo = FALSE) { UseMethod("sampleValue") } #' @export sampleValue.Param = function(par, discrete.names = FALSE, trafo = FALSE) { assertFlag(discrete.names) assertFlag(trafo) type = par$type if (!is.null(par$len) && is.na(par$len)) { stop("Cannot sample with NA length!") } if (isNumericTypeString(type)) { if (anyInfinite(c(par$lower, par$upper))) { stop("Cannot sample with Inf bounds!") } if (isIntegerTypeString(type)) { x = as.integer(round(runif(par$len, min = par$lower - 0.5, max = par$upper + 0.5))) } else { x = runif(par$len, min = par$lower, max = par$upper) } } else if (isLogicalTypeString(type)) { x = sample(c(TRUE, FALSE), par$len, replace = TRUE) } else if (isDiscreteTypeString(type, FALSE)) { x = sample(names(par$values), par$len, replace = TRUE) if (!discrete.names) { x = if (type == "discretevector") { par$values[x] } else { par$values[[x]] } } } else { stopf("Cannot generate random value for %s variable!", type) } if (trafo && !is.null(par$trafo)) { x = par$trafo(x) } # if the components have names, set them if (!is.null(par$cnames)) { names(x) = par$cnames } return(x) } #' @export sampleValue.ParamSet = function(par, discrete.names = FALSE, trafo = FALSE) { # sample value for each param, do it until we a get one which is not forbidden repeat { val = lapply(par$pars, sampleValue, discrete.names = discrete.names, trafo = trafo) if (is.null(par$forbidden) || !isForbidden(par, val)) { break } } # set conditional params to NA is condition not OK val = lapply(seq_along(val), function(i) { if (!is.null(par$pars[[i]]$requires) && !requiresOk(par$pars[[i]], val)) { type = par$pars[[i]]$type type = switch(type, numericvector = "numeric", integervector = "integer", logicalvector = "logical", discrete = "character", discretevector = "character", type ) as(NA, type) } else { val[[i]] } }) names(val) = names(par$pars) return(val) } #' @title Sample n random values from a parameter or a parameter set uniformly. #' #' @template desc_dep_pars_na #' #' @template arg_par_or_set #' @param n (`integer(1)`)\cr #' Number of values. #' @template arg_disc_names #' @template arg_trafo #' @return `list`. For consistency always a list is returned. #' @export #' @examples #' p = makeIntegerParam("x", lower = -10, upper = 10) #' sampleValues(p, 4) #' #' p = makeNumericParam("x", lower = -10, upper = 10) #' sampleValues(p, 4) #' #' p = makeLogicalParam("x") #' sampleValues(p, 4) #' #' ps = makeParamSet( #' makeNumericParam("u", lower = 1, upper = 10), #' makeIntegerParam("v", lower = 1, upper = 10), #' makeDiscreteParam("w", values = 1:2) #' ) #' sampleValues(ps, 2) sampleValues = function(par, n, discrete.names = FALSE, trafo = FALSE) { assert(checkClass(par, "Param"), checkClass(par, "ParamSet")) n = asInt(n) assertFlag(discrete.names) replicate(n, sampleValue(par, discrete.names = discrete.names, trafo = trafo), simplify = FALSE) } ParamHelpers/R/updateParVals.R0000644000176000001440000000454613636350000015771 0ustar ripleyusers#' @title Insert par.vals to old ones with meeting requirements #' @description Update the values of a given parameter setting with a new #' parameter setting. Settings that do not meet the requirements anymore will be #' deleted from the first given parameter setting. Default values of the Param #' Set are respected to check if the new param settings meet the requirements. #' #' @template arg_parset #' @param old.par.vals [list]\cr #' Param Values to be updated. #' @param new.par.vals [list]\cr #' New Param Values to update the `old.par.vals`. #' @param warn [logical]\cr #' Whether a warning should be shown, if a param setting from `old.par.vals` #' is dropped. Default is `FALSE`. #' @return [`list`]. #' @export updateParVals = function(par.set, old.par.vals, new.par.vals, warn = FALSE) { assertList(old.par.vals, names = "named") assertList(new.par.vals, names = "named") assertClass(par.set, "ParamSet") # we might want to check requires with defaults that are not overwritten by new.par.vals usable.defaults = getDefaults(par.set) usable.defaults = usable.defaults[names(usable.defaults) %nin% names(new.par.vals)] repeat { # we repeat to include parameters which depend on each other by requirements # candidates are params of the old par.vals we might still need. candidate.par.names = setdiff(names(old.par.vals), names(new.par.vals)) for (pn in candidate.par.names) { # If all requirement parameters for the candidate are in the new.par.vals and if the requirements are met if (all(getRequiredParamNames(par.set$pars[[pn]]) %in% names(new.par.vals)) && requiresOk(par.set$pars[[pn]], new.par.vals)) { new.par.vals[pn] = old.par.vals[pn] # keep old.par.val in new.par.vals as it meets the requirements } else if (all(getRequiredParamNames(par.set$pars[[pn]]) %in% names(usable.defaults)) && requiresOk(par.set$pars[[pn]], usable.defaults)) { new.par.vals[pn] = old.par.vals[pn] # keep old.par.val as it meets requirement via defaults } else if (warn) { # otherwise we can drop the old par.val because it does not meet the requirements. warningf("ParamSetting %s was dropped.", convertToShortString(old.par.vals[pn])) } } # break if no changes were made if (identical(candidate.par.names, setdiff(names(old.par.vals), names(new.par.vals)))) break } return(new.par.vals) } ParamHelpers/R/hasForbidden.R0000644000176000001440000000033213633666270015613 0ustar ripleyusers#' Check parameter set for forbidden region. #' #' @template arg_parset #' @return `logical(1)`. #' @export hasForbidden = function(par.set) { assertClass(par.set, "ParamSet") return(!is.null(par.set$forbidden)) } ParamHelpers/R/hasFiniteBoxConstraints.R0000644000176000001440000000134713633666270020045 0ustar ripleyusers#' Checks if a parameter or each parameter of a parameter set has ONLY finite lower and upper bounds. #' #' @template arg_par_or_set #' @template arg_dict #' @return `logical(1)` #' @export hasFiniteBoxConstraints = function(par, dict = NULL) { UseMethod("hasFiniteBoxConstraints") } #' @export hasFiniteBoxConstraints.Param = function(par, dict = NULL) { bounds = c(getLower(par, dict = dict), getUpper(par, dict = dict)) if (length(bounds) == 0) { return(TRUE) } return(all(is.finite(bounds))) } #' @export hasFiniteBoxConstraints.ParamSet = function(par, dict = NULL) { bounds = c(getLower(par, dict = dict), getUpper(par, dict = dict)) if (length(bounds) == 0) { return(TRUE) } return(all(is.finite(bounds))) } ParamHelpers/R/renderOptPathPlot.R0000644000176000001440000003553713636346430016654 0ustar ripleyusers#' @title Function for plotting optimization paths. #' #' @description #' Same as [plotOptPath()], but renders the plots for just 1 iteration #' and returns a list of plots instead of printing the plot. Useful, if you want #' to extract single plots or to edit the ggplots by yourself. #' #' @param op [OptPath]\cr #' Optimization path. #' @param iter (`integer(1)`)\cr #' Selected iteration of `x` to render plots for. #' @param x.over.time (`list` | NULL)\cr #' List of vectors of x-variables, either specified via name or id. #' If specified via names, also extra measurements from the opt.path can be #' selected. #' Maximum length for each vector is 5. For each list-element a line-plot iteration versus variable is generated. #' If the vector has length > 2 only mean values per iteration are plotted as lines, if vector has length 1 every point is plotted. #' Default is to plot all variables into as few plots as possible. #' Note that discrete variables are converted to numeric, if specified in the same vector with numerics. #' Moreover, if more than 1 point per iteration exists, mean values are calculated. #' This is also done for factor variables! We recommend you to specify this argument in a useful way. #' @param y.over.time (`list` | NULL)\cr #' List of vectors of y-variables, either specified via name or id. #' If specified via names, also extra measurements from the opt.path can be selected. #' Maximum length for each vector is 5. #' For each list-element a line-plot iteration versus variable is generated. #' If the vector has length > 2 only mean values per iteration are plotted as lines, if vector has length 1 every point is plotted. #' Default is to plot all variables into as few plots as possible. #' Note that discrete variables are converted to numeric, if specified in the same vector with numerics. #' Moreover, if more than 1 point per iteration exists, mean values are calculated. #' This is also done for factor variables! We recommend you to specify this argument in a useful way. #' @param contour.name (`character(1)` | NULL)\cr #' It is possible to overlay the XSpace plot with an contour plot. This is #' only possible, if the XSpace has exact 2 numeric and 0 discrete variable. #' Consider subsetting your variables to use this feature! contour.name is the #' name of the target variable that will be used for the contour lines. #' Default is to use the first target variable, if it is possible to add #' contour lines. #' @template arg_opplotter_lims #' @param alpha (`logical(1)`)\cr #' Activates or deactivates the alpha fading for the plots. Default is `TRUE`. #' @param log [character]\cr #' Vector of variable names. All of this variable logarithmized in every plot. #' Default is NULL - no logarithm is applied. Note that, if an variable has #' only negative value, it is multiplied with -1. For variables with both #' positive and negative values you have to do your own data preprocessing. #' @param colours (`character(4)`)\cr #' Colours of the points/lines for the four point types init, seq, prob and #' marked. Default is red for init, blue for seq, green for prob and orange #' for marked. #' @param size.points (`numeric(4)` | NULL)\cr #' Size of points in the plot, default is 3. #' @param size.lines (`numeric(4)` | NULL)\cr #' Size of lines in the plots, default is 1.5. #' @param impute.scale (`numeric(1)`)\cr #' Numeric missing values will be replaced by `max + impute.scale * (max - min)`. #' Default is `1`. #' @param impute.value (`character(1)`)\cr #' Factor missing values will be replaced by `impute.value`. Default is `missing`. #' @param scale (`character(1)`)\cr #' Parameter `scale` from the function [GGally::ggparcoord()] which is used for #' the multiD-case. Default is `std`. #' @param ggplot.theme #' Theme for the ggplots. Can be generated by [ggplot2::theme()]. Default is #' `ggplot2::theme(legend.position = "top")`. #' @param marked (`integer` | `character(1)` | NULL)\cr #' \dQuote{best} or indices of points that should be marked in the plots. #' If `marked = "best"` the best point for single crit optimization #' respectively the pareto front for multi crit optimization is marked. #' Default is `NULL` (no points are marked). #' @param subset.obs [integer]\cr #' Vector of indices to subset of observations to be plotted, default is all #' observations. All indices must be available in the opt.path. But, to enable #' subsetting over multiple iterations, not all indices must be available in #' the current iteration. Indices not available in the current iteration will #' be ignored. Default is all observations. #' @param subset.vars (`integer` | `character`)\cr #' Subset of variables (x-variables) to be plotted. Either vector of indices #' or names. Default is all variables. #' @param subset.targets (`integer` | `character`)\cr #' Subset of target variables (y-variables) to be plotted. Either vector of #' indices or names. Default is all variables #' @param short.x.names [character]\cr #' Short names for x variables that are used as axis labels. Note you can #' only give shortnames for variables you are using in `subset.vars` #' @param short.y.names [character]\cr #' Short names for y variables that are used as axis labels. Note you can #' only give shortnames for variables you are using in `subset.targets` #' @param short.rest.names [character]\cr #' Short names for rest variables that are used as axis labels. Note you can #' only give shortnames for variables you are used in `x.over.time` #' or `y.over.time`. #' @return List of plots. List has up to elements: #' plot.x: Plot for XSpace. If both X and Y are 1D, Plot for both #' plot.y: Plot for YSpace. If both X and Y are 1D, NULL. #' plot.x.over.time: List of plots for x over time. Can also be NULL. #' plot.y.over.time: List of plots for y over time. Can also be NULL. #' @export renderOptPathPlot = function(op, iter, x.over.time, y.over.time, contour.name = NULL, xlim = list(), ylim = list(), alpha = TRUE, log = NULL, colours = c("red", "blue", "green", "orange"), size.points = 3, size.lines = 1.5, impute.scale = 1, impute.value = "missing", scale = "std", ggplot.theme = ggplot2::theme(legend.position = "top"), marked = NULL, subset.obs, subset.vars, subset.targets, short.x.names, short.y.names, short.rest.names) { requirePackages(c("GGally", "ggplot2"), why = "renderOptPathPlot", default.method = "load") iters.max = max(getOptPathDOB(op)) assertClass(op, "OptPath") assertInt(iter, lower = 0L, upper = iters.max) assertFlag(alpha) assertCharacter(colours, len = 4L) assertNumber(size.points) assertNumber(size.points) assertNumber(impute.scale) assertCharacter(impute.value, len = 1L) assertChoice(scale, choices = c("std", "robust", "uniminmax", "globalminmax", "center", "centerObs")) assertClass(ggplot.theme, classes = c("theme", "gg")) if (!is.null(marked)) { if (is.character(marked)) { if (marked != "best") { stop("Marked must either be 'best' or an integerish vector.") } } else { marked = asInteger(marked) } } # Get Plotting Data and extract everything from the helper data = getAndSubsetPlotData(op, iter, subset.obs, subset.vars, subset.targets, marked, alpha, impute.scale, impute.value) op.x = data$op.x op.y = data$op.y op.rest = data$op.rest dob = data$dob .alpha = data$.alpha .type = data$.type x.names = data$x.names y.names = data$y.names rest.names = data$rest.names dim.x = length(data$x.names) dim.y = length(data$y.names) assertSubset(log, choices = c(x.names, y.names, rest.names)) # set defaults for the short names in x, y and rest if (missing(short.x.names)) { short.x.names = x.names } else { assertCharacter(short.x.names, len = dim.x) } if (missing(short.y.names)) { short.y.names = y.names } else { assertCharacter(short.y.names, len = dim.y) } if (missing(short.rest.names)) { short.rest.names = rest.names } else { assertCharacter(short.rest.names, len = length(rest.names)) } # set and check x and y lims, if needed lims = getOptPathLims(xlim, ylim, op.x, op.y, iter, 0.05) xlim = lims$xlim ylim = lims$ylim # Set defaults for the over time plots or check the given params if (missing(x.over.time)) { x.over.time = split(x.names, rep(1:ceiling(dim.x / 5), each = 5, length.out = dim.x)) } else { if (!is.null(x.over.time)) { if (!is.list(x.over.time)) { x.over.time = list(x.over.time) } assertList(x.over.time) for (vec in x.over.time) { if (is.character(vec)) { assertSubset(x = vec, choices = c(x.names, rest.names), empty.ok = FALSE) } else { assertNumeric(x = vec, lower = 1L, upper = dim.x, any.missing = FALSE, unique = TRUE) } } } } if (missing(y.over.time)) { y.over.time = split(y.names, rep(1:ceiling(dim.y / 5), each = 5, length.out = dim.y)) } else { if (!is.null(y.over.time)) { if (!is.list(y.over.time)) { y.over.time = list(y.over.time) } assertList(y.over.time) for (vec in y.over.time) { if (is.character(vec)) { assertSubset(x = vec, choices = c(y.names, rest.names), empty.ok = FALSE) } else { assertNumeric(x = vec, lower = 1L, upper = dim.y, any.missing = FALSE, unique = TRUE) } } } } if (!is.null(contour.name)) { if (length(x.names) != 2 || any(apply(op.x, 2, class) != "numeric")) { stop("Contour lines can only be applied if there are exacr 2 numeric x variables. Consider subsetting your variables.") } assertChoice(contour.name, y.names) } else { if (length(x.names) == 2 && all(apply(op.x, 2, class) == "numeric")) { contour.name = y.names[1L] } } # get classes of params (numeric or factor) classes.x = BBmisc::vcapply(op.x, function(x) class(x)) classes.y = BBmisc::vcapply(op.y, function(x) class(x)) # So much for the data and the input, now the plots # Special case: X and Y are 1D if (dim.x == 1L && dim.y == 1L) { pl1 = plot2D(cbind(x = op.x, y = op.y), .alpha, .type, log, names = c(x.names, y.names), short.names = c(short.x.names, short.y.names), space = "both", iter = iter, classes = c(classes.x, classes.y), xlim = xlim[["XSpace"]], ylim = xlim[["YSpace"]], colours = colours, size = size.points, ggplot.theme = ggplot.theme) pl2 = NULL } else { # plot 1: x-space if (dim.x == 1L && classes.x == "numeric") { pl1 = plot1DNum(op.x, .alpha, .type, log, names = x.names, short.names = short.x.names, space = "x", iter = iter, xlim = xlim[["XSpace"]], colours = colours, ggplot.theme = ggplot.theme) } if (dim.x == 1L && classes.x == "factor") { pl1 = plot1DDisc(op.x, .alpha, .type, log, names = x.names, short.names = short.x.names, space = "x", iter = iter, ylim = ylim[["XSpace"]], colours = colours, ggplot.theme = ggplot.theme) } if (dim.x == 2L) { pl1 = plot2D(op.x, .alpha, .type, log, names = x.names, short.names = short.x.names, y.name = contour.name, op.y = op.y, space = "x", iter = iter, classes = classes.x, xlim = xlim[["XSpace"]], ylim = ylim[["XSpace"]], colours = colours, size = size.points, ggplot.theme = ggplot.theme) } if (dim.x > 2L) { pl1 = plotMultiD(op.x, .alpha, .type, log, names = x.names, short.names = short.x.names, space = "x", iter = iter, colours = colours, size = size.lines, scale = scale, ggplot.theme = ggplot.theme) } # plot 2: y-space if (dim.y == 1L && classes.y == "numeric") { pl2 = plot1DNum(op.y, .alpha, .type, log, names = y.names, short.names = short.y.names, space = "y", iter = iter, xlim = xlim[["YSpace"]], colours = colours, ggplot.theme = ggplot.theme) } if (dim.y == 1L && classes.y == "factor") { pl2 = plot1DDisc(op.y, .alpha, .type, log, names = y.names, short.names = short.y.names, space = "y", iter = iter, ylim = ylim[["YSpace"]], colours = colours, ggplot.theme = ggplot.theme) } if (dim.y == 2L) { pl2 = plot2D(op.y, .alpha, .type, log, names = y.names, short.names = short.y.names, space = "y", iter = iter, classes = classes.y, xlim = xlim[["YSpace"]], ylim = ylim[["YSpace"]], colours = colours, size = size.points, ggplot.theme = ggplot.theme) } if (dim.y > 2L) { pl2 = plotMultiD(op.y, .alpha, .type, log, names = y.names, short.names = short.y.names, space = "y", iter = iter, colours = colours, size = size.lines, scale = scale, ggplot.theme = ggplot.theme) } } # plot 3: x space over time pl3 = vector(mode = "list", length = length(x.over.time)) for (i in seq_along(x.over.time)) { # extract variable information from over.time vars = x.over.time[[i]] # if specified via character vector, convert to numeric if (is.character(vars)) { var.inds = which(c(names(op.x), names(op.rest)) %in% vars) } names = c(x.names, rest.names)[var.inds] short.names = c(short.x.names, short.rest.names)[var.inds] if (length(vars) == 1) { pl3[[i]] = oneVariableOverTime(op = cbind(op.x, op.rest), .alpha = .alpha, .type = .type, dob = dob, log = log, names = names, short.names = short.names, iter = iter, colours = colours, size.points = size.points, size.lines = size.lines, ggplot.theme = ggplot.theme) } else { pl3[[i]] = multiVariablesOverTime(op = cbind(op.x, op.rest), .alpha = .alpha, dob = dob, log = log, names = names, short.names = short.names, space = "XSpace", iter = iter, colours = colours, ggplot.theme = ggplot.theme) } } if (length(pl3) == 0) { pl3 = NULL } # plot 4: y space over time pl4 = vector(mode = "list", length = length(y.over.time)) for (i in seq_along(y.over.time)) { # extract variable information from over.time vars = y.over.time[[i]] # if specified via character vector, convert to numeric if (is.character(vars)) { var.inds = which(c(names(op.y), names(op.rest)) %in% vars) } names = c(y.names, rest.names)[var.inds] short.names = c(short.y.names, short.rest.names)[var.inds] if (length(vars) == 1) { pl4[[i]] = oneVariableOverTime(op = cbind(op.y, op.rest), .alpha = .alpha, .type = .type, dob = dob, log = log, names = names, short.names = short.names, iter = iter, colours = colours, size.points = size.points, size.lines = size.lines, ggplot.theme = ggplot.theme) } else { pl4[[i]] = multiVariablesOverTime(op = cbind(op.y, op.rest), .alpha = .alpha, dob = dob, log = log, names = names, short.names = short.names, space = "YSpace", iter = iter, colours = colours, ggplot.theme = ggplot.theme) } } if (length(pl4) == 0) { pl4 = NULL } return(list(plot.x = pl1, plot.y = pl2, plot.x.over.time = pl3, plot.y.over.time = pl4)) } ParamHelpers/R/getRequirements.R0000644000176000001440000000151613633666270016413 0ustar ripleyusers#' @title Return all require-expressions of a param set. #' #' @description #' Returns all `require`s-objects of a param set as a list. #' #' @template arg_parset #' @param remove.null (`logical(1)`)\cr #' If not set, params without a requires-setting will result in a `NULL` #' element in the returned list, otherwise they are removed. Default is #' code{TRUE}. #' @return xnamed `list`. #' Named list of require-call-objects, lengths corresponds to number of params #' (potentially only the subset with requires-field), named with with param #' ids. #' @export getRequirements = function(par.set, remove.null = TRUE) { assertClass(par.set, "ParamSet") assertFlag(remove.null) res = extractSubList(par.set$pars, "requires", simplify = FALSE, use.names = TRUE) if (remove.null) { res = filterNull(res) } return(res) } ParamHelpers/R/hasRequires.R0000644000176000001440000000100013633666270015507 0ustar ripleyusers#' @title Check parameter / parameter set for requirements / dependencies. #' #' @description #' `TRUE` iff the parameter has any requirements or any parameter in the set has #' requirements. #' #' @template arg_par_or_set #' @return `logical(1)`. #' @export hasRequires = function(par) { UseMethod("hasRequires") } #' @export hasRequires.Param = function(par) { return(!is.null(par$requires)) } #' @export hasRequires.ParamSet = function(par) { return(any(vapply(par$pars, hasRequires, logical(1L)))) } ParamHelpers/R/paramValueToString.R0000644000176000001440000000525313636350076017016 0ustar ripleyusers#' @title Convert a value to a string. #' #' @description #' Useful helper for logging. #' For discrete parameter values always the name of the discrete value is used. #' #' @template arg_par_or_set #' @param x (any)\cr #' Value for parameter or value for parameter set. In the latter case it must #' be named list. For discrete parameters their values must be used, not their #' names. #' @param show.missing.values (`logical(1)`)\cr #' Display \dQuote{NA} for parameters, which have no setting, because their #' requirements are not satisfied (dependent parameters), instead of #' displaying nothing? Default is `FALSE`. #' @param num.format (`character(1)`)\cr #' Number format for output of numeric parameters. See the details section of #' the manual for [base::sprintf()] for details. #' @return `character(1)`. #' @export #' @examples #' p = makeNumericParam("x") #' paramValueToString(p, 1) #' paramValueToString(p, 1.2345) #' paramValueToString(p, 0.000039) #' paramValueToString(p, 8.13402, num.format = "%.2f") #' #' p = makeIntegerVectorParam("x", len = 2) #' paramValueToString(p, c(1L, 2L)) #' #' p = makeLogicalParam("x") #' paramValueToString(p, TRUE) #' #' p = makeDiscreteParam("x", values = list(a = NULL, b = 2)) #' paramValueToString(p, NULL) #' #' ps = makeParamSet( #' makeNumericVectorParam("x", len = 2L), #' makeDiscreteParam("y", values = list(a = NULL, b = 2)) #' ) #' paramValueToString(ps, list(x = c(1, 2), y = NULL)) paramValueToString = function(par, x, show.missing.values = FALSE, num.format = "%.3g") { assertFlag(show.missing.values) assertString(num.format) UseMethod("paramValueToString") } #' @export paramValueToString.Param = function(par, x, show.missing.values = FALSE, num.format = "%.3g") { # handle missings if (isScalarNA(x)) { if (show.missing.values) { return("NA") } else { return("") } } if (isDiscrete(par, include.logical = FALSE)) { x = discreteValueToName(par, x) } return(convertToShortString(x, num.format = num.format)) } #' @export paramValueToString.ParamSet = function(par, x, show.missing.values = FALSE, num.format = "%.3g") { assertList(x) if (!isProperlyNamed(x)) { stop("'x' must be a properly named list!") } rest = setdiff(names(x), names(par$pars)) if (length(rest) > 0L) { stopf("Not all names of 'x' occur in par set 'par': %s", collapse(rest)) } res = character(0L) for (i in seq_along(x)) { pn = names(x)[i] val = x[[pn]] if (show.missing.values || !isScalarNA(val)) { p = par$pars[[pn]] res[length(res) + 1] = sprintf("%s=%s", pn, paramValueToString(p, val, show.missing.values, num.format)) } } return(collapse(res, sep = "; ")) } ParamHelpers/R/generateDesign.R0000644000176000001440000002521313633666270016154 0ustar ripleyusers# FIXME: generateDesign will NOT work if there are dependencies # over multiple levels of params and one only states the dependency only # wrt to the "last" param. also see daniels unit test. # it works as long all dependencies are stated, we need to at least document this # FIXME: it really makes no sense to calculate the distance for params that are NA # when we do the design and augment it right? think about what happens here #' @title Generates a statistical design for a parameter set. #' #' @description #' The following types of columns are created: #' \tabular{ll}{ #' numeric(vector) \tab `numeric` \cr #' integer(vector) \tab `integer` \cr #' discrete(vector) \tab `factor` (names of values = levels) \cr #' logical(vector) \tab `logical` #' } #' If you want to convert these, look at [BBmisc::convertDataFrameCols()]. #' Dependent parameters whose constraints are unsatisfied generate `NA` entries in their #' respective columns. #' For discrete vectors the levels and their order will be preserved, even if not all levels are present. #' #' Currently only lhs designs are supported. #' #' The algorithm currently iterates the following steps: #' \enumerate{ #' \item{We create a space filling design for all parameters, disregarding `requires`, #' a `trafo` or the forbidden region.} #' \item{Forbidden points are removed.} #' \item{Parameters are trafoed (potentially, depending on the setting of argument `trafo`); #' dependent parameters whose constraints are unsatisfied are set to `NA` entries.} #' \item{Duplicated design points are removed. Duplicated points are not generated in a #' reasonable space-filling design, but the way discrete parameters and also parameter dependencies #' are handled make this possible.} #' \item{If we removed some points, we now try to augment the design in a space-filling way #' and iterate.} #' } #' #' Note that augmenting currently is somewhat experimental as we simply generate #' missing points via new calls to [lhs::randomLHS()], but do not add points so #' they are maximally far away from the already present ones. The reason is that #' the latter is quite hard to achieve with complicated dependencies and #' forbidden regions, if one wants to ensure that points actually get added... #' But we are working on it. #' #' Note that if you have trafos attached to your params, the complete creation #' of the design (except for the detection of invalid parameters w.r.t to their #' `requires` setting) takes place on the UNTRANSFORMED scale. So this function #' creates, e.g., a maximin LHS design on the UNTRANSFORMED scale, but not #' necessarily the transformed scale. #' #' `generateDesign` will NOT work if there are dependencies over multiple levels #' of parameters and the dependency is only given with respect to the #' \dQuote{previous} parameter. A current workaround is to state all #' dependencies on all parameters involved. (We are working on it.) #' #' @template arg_gendes_n #' @template arg_parset #' @param fun (`function`)\cr #' Function from package lhs. #' Possible are: [lhs::maximinLHS()], [lhs::randomLHS()], #' [lhs::geneticLHS()], [lhs::improvedLHS()], [lhs::optAugmentLHS()], #' [lhs::optimumLHS()] #' Default is [lhs::randomLHS()]. #' @param fun.args (`list`)\cr #' List of further arguments passed to `fun`. #' @template arg_trafo #' @param augment (`integer(1)`)\cr #' Duplicated values and forbidden regions in the parameter space can lead to #' the design becoming smaller than `n`. With this option it is possible to #' augment the design again to size `n`. It is not guaranteed that this always #' works (to full size) and `augment` specifies the number of tries to #' augment. If the the design is of size less than `n` after all tries, a #' warning is issued and the smaller design is returned. Default is 20. #' @template ret_gendes_df #' @export #' @examples #' ps = makeParamSet( #' makeNumericParam("x1", lower = -2, upper = 1), #' makeIntegerParam("x2", lower = 10, upper = 20) #' ) #' # random latin hypercube design with 5 samples: #' generateDesign(5, ps) #' #' # with trafo #' ps = makeParamSet( #' makeNumericParam("x", lower = -2, upper = 1), #' makeNumericVectorParam("y", len = 2, lower = 0, upper = 1, trafo = function(x) x / sum(x)) #' ) #' generateDesign(10, ps, trafo = TRUE) generateDesign = function(n = 10L, par.set, fun, fun.args = list(), trafo = FALSE, augment = 20L) { n = asInt(n) z = doBasicGenDesignChecks(par.set) lower = z$lower upper = z$upper requirePackages("lhs", why = "generateDesign", default.method = "load") if (missing(fun)) { fun = lhs::randomLHS } else { assertFunction(fun) } assertList(fun.args) assertFlag(trafo) augment = asInt(augment, lower = 0L) ### precompute some useful stuff pars = par.set$pars lens = getParamLengths(par.set) k = sum(lens) pids = getParamIds(par.set, repeated = TRUE, with.nr = TRUE) par.ids.each = lapply(pars, getParamIds, repeated = TRUE, with.nr = TRUE) par.nas.each = lapply(pars, getParamNA, repeated = FALSE) req.vectorized = determineReqVectorized(pars) lower2 = setNames(rep(NA_real_, k), pids) lower2 = insert(lower2, lower) upper2 = setNames(rep(NA_real_, k), pids) upper2 = insert(upper2, upper) values = getParamSetValues(par.set) types.df = getParamTypes(par.set, df.cols = TRUE) types.df[types.df == "factor"] = "character" nmissing = n # result objects res = data.frame() des = matrix(nrow = 0, ncol = k) for (iter in seq_len(augment)) { ### get design, types converted, trafos, conditionals set to NA # create new design or augment if we already have some points newdes = if (nmissing == n) { do.call(fun, insert(list(n = nmissing, k = k), fun.args)) } else { lhs::randomLHS(nmissing, k = k) } # taken and adapted from individual Param Objects in mlr-org/paradox getMapping = function(i) { # Numeric if (types.df[i] == "numeric") { newdes[,i] * (upper2[i] - lower2[i]) + lower2[i] } else if (types.df[i] == "integer") { # Integer as.integer(floor(newdes[,i] * ((upper2[i] - lower2[i]) + 1L) * (1 - 1e-16)) + lower2[i]) # Logic } else if (types.df[i] == "logical") { newdes[,i] < 0.5 # Discrete } else if (types.df[i] == "character") { values[[i]][floor(newdes[,i] * length(values[[i]]) * (1 - 1e-16)) + 1] } else { stopf("%s for Param %s is an unsupported type.", types.df[i], pids[i]) } } newres = mapDfc(seq_along(pids), getMapping) colnames(newres) = pids # check each row if forbidden, then remove if (hasForbidden(par.set)) { # FIXME: this is pretty slow, but correct fb = unlist(lapply(dfRowsToList(newres, par.set = par.set), function(x) { isForbidden(x, par.set = par.set) })) newres = newres[!fb, , drop = FALSE] newdes = newdes[!fb, , drop = FALSE] } if (trafo) { newres = applyTrafos(newres, pars) } newres = setRequiresToNA(newres, pars, par.ids.each, par.nas.each, req.vectorized) # add to result (design matrix and data.frame) des = rbind(des, newdes) res = rbind(res, newres) # remove duplicates to.remove = duplicated(res) des = des[!to.remove, , drop = FALSE] res = res[!to.remove, , drop = FALSE] nmissing = n - nrow(res) # Enough points? We are done! if (nmissing == 0L) { break } } if (nrow(res) < n) { warningf("generateDesign could only produce %i points instead of %i!", nrow(res), n) } colnames(res) = pids res = fixDesignFactors(res, par.set) attr(res, "trafo") = trafo return(res) } # applies the trafo to each parameter # @param res data.frame() # with columns named accroding to getParamIds(par, repeated = TRUE, with.nr = TRUE) (so multiple columns for vector params) # @pars list() # the ps$pars part of a param set # @value data.frame() applyTrafos = function(res, pars) { for (par in pars) { if (!is.null(par$trafo)) { ids = getParamIds(par, repeated = TRUE, with.nr = TRUE) if (par$len == 1) { # we expect, that the trafo works vectorized for normal params res[, ids] = par$trafo(res[, ids]) } else { # for vector params the trafo has to work on the single vector for (i in seq_len(nrow(res))) { res[i, ids] = par$trafo(res[i, ids]) } } } } res } # determines if the requirements work vectorized accrding to a simple heuristic # @param pars list() # the ps$pars part of a param set # @value logical named # TRUE for each column that I can evaluate vectorized determineReqVectorized = function(pars) { # heuristic if we allow this requirement to be evaluated in an vectorized fashion vapply(X = lapply(pars, function(p) p$requires), function(req) { # vectorized if no "&&", "||" or "(" is detected !grepl(x = deparse(req), pattern = "\\|\\||&&|\\(") }, FUN.VALUE = logical(1)) } # Sets values of params to NA if requirements are not evaluated to TRUE (rowwise) # @param res data.frame(n,m) # The design # @param pars list() # the ps$pars part of a param set # @param pars.ids.each list() # the colnames that are used by each parameter (especially important for vector params, otherwise ist just list(paramA = "paramA")) # @param pars.nas.each list() # the na type (e.g NA_character) that should be filled in if req is not met (important so that we do not destroy the right column type) # @param req.vectorized named logical() # TRUE for each column that I can evaluate the req vectorized # @value data.frame() setRequiresToNA = function(res, pars, par.ids.each = NULL, par.nas.each = NULL, req.vectorized = NULL) { # these values can be passed manually to make this function faster if it is called multiple times because the single S3 function calls can sum up to some seconds! if (is.null(par.ids.each)) { par.ids.each = lapply(pars, getParamIds, repeated = TRUE, with.nr = TRUE) } if (is.null(par.nas.each)) { par.nas.each = lapply(pars, getParamNA, repeated = FALSE) } if (is.null(req.vectorized)) { req.vectorized = determineReqVectorized(pars) } for (par in pars) { req = par$requires if (!is.null(req)) { # set rows to NA 1) where req does not evalue to true AND 2) where the row is not already NA if (req.vectorized[par$id]) { set.to.na = !eval(req, res) } else { # unfortunately we allowed requirements to be not vectorized set.to.na = !vapply(seq_len(nrow(res)), function(i) { eval(req, res[i,]) }, FUN.VALUE = logical(1)) } set.to.na = set.to.na & !is.na(res[[par.ids.each[[par$id]][1]]]) res[set.to.na, par.ids.each[[par$id]]] = par.nas.each[[par$id]] } } res } ParamHelpers/R/getParamNr.R0000644000176000001440000000131613633666270015266 0ustar ripleyusers#' @title Return number of parameters in set. #' #' @description #' Either number of parameters or sum over parameter lengths. #' #' @template arg_parset #' @param devectorize (`logical(1)`)\cr #' Sum over length of vector parameters? #' Default is code{FALSE}. #' @return [`integer`]. #' @examples #' ps = makeParamSet( #' makeNumericParam("u"), #' makeDiscreteVectorParam("x", len = 2, values = c("a", "b")) #' ) #' getParamNr(ps) #' getParamNr(ps, devectorize = TRUE) #' @export getParamNr = function(par.set, devectorize = FALSE) { assertClass(par.set, "ParamSet") assertFlag(devectorize) if (devectorize) { return(sum(getParamLengths(par.set))) } else { return(length(par.set$pars)) } } ParamHelpers/R/OptPath_plotter.R0000644000176000001440000001165713633666270016367 0ustar ripleyusers#' @title Plot method for optimization paths. #' #' @description Plot method for every type of optimization path, containing any #' numbers and types of variables. For every iteration up to 4 types of plots #' can be generated: One plot for the distribution of points in X and Y space #' respectively and plots for the trend of specified X variables, Y variables #' and extra measures over the time. #' #' @param op (`OptPath`)\cr #' Optimization path. #' @param iters (`integer` | NULL)\cr #' Vector of iterations which should be plotted one after another. If `NULL`, #' which is the default, only the last iteration is plotted. Iteration 0 plots #' all elements with dob = 0. Note that the plots for iteration i contains all #' observations alive in iteration i. #' @param pause (`logical(1)`)\cr #' Should the process be paused after each iteration? #' Default is `TRUE`. #' @template arg_opplotter_lims #' @param title (`character(1)`)\cr #' Main title for the arranged plots, default is Optimization Path Plots. #' @param ... #' Additional parameters for [renderOptPathPlot()]. #' @return NULL #' @export #' plotOptPath = function(op, iters, pause = TRUE, xlim = list(), ylim = list(), title = "Optimization Path Plots", ...) { requirePackages(c("grid", "gridExtra"), why = "plotOptPath") if (missing(iters)) { iters = max(getOptPathDOB(op)) } assertClass(op, "OptPath") assertIntegerish(iters, lower = 0L, upper = max(getOptPathDOB(op)), any.missing = FALSE) assertFlag(pause) assertCharacter(title, len = 1L) # Set and check x and y lims, if needed # Consider only points alive during at least 1 plotted iteration # Set and check x and y lims, if needed data = getAndSubsetPlotData(op, iters, ...) lims = getOptPathLims(xlim, ylim, data$op.x, data$op.y, iters, 0.05) xlim = lims$xlim ylim = lims$ylim # Helper to arrange plot via gridExtra and pause process arrangePlots = function(plots, iter, iters) { # align plots plots = toGTable(plots) max.width = getMaxPlotWidth(plots) plots = toAlignedGTable(plots, max.width) if (!is.null(plots$plot.x.over.time)) { plots$plot.x.over.time = gridExtra::arrangeGrob(grobs = plots$plot.x.over.time, ncol = 1L) } if (!is.null(plots$plot.y.over.time)) { plots$plot.y.over.time = gridExtra::arrangeGrob(grobs = plots$plot.y.over.time, ncol = 1L) } plot.top = Filter(Negate(is.null), list(plots$plot.x, plots$plot.y)) plot.top = gridExtra::arrangeGrob(grobs = plot.top, nrow = 1L) plot.bottom = Filter(Negate(is.null), list(plots$plot.x.over.time, plots$plot.y.over.time)) if (length(plot.bottom) > 0L) { plot.bottom = do.call(gridExtra::arrangeGrob, c(plot.bottom, nrow = 1L)) plots = list(plot.top, plot.bottom) } else { plots = list(plot.top) } gridExtra::grid.arrange(grobs = plots, ncol = 1L, main = title) if (pause && iter != getLast(iters)) { pause() } } # Get rendered data and plot it for every iteration for (iter in iters) { plots = renderOptPathPlot(op, iter = iter, xlim = xlim, ylim = ylim, ...) arrangePlots(plots, iter, iters) } return(invisible(NULL)) } # Helper functions to ensure nice plot alignment. # # If plots are aligned in a grid via gridExtra::grid.arrange we are frequently # faced with the ugly cosmetic problem, that the plot areas are unaligned if # different plots have different y-axis scales. # # The following helper functions ensure nice alignment by doing three things: # 1) transform ggplot objects to gtable objects. # 2) extract the maximum left margin width of the gtables as a unit object. # 3) Assign the maximum left margin width determined in 2) to all gtable # # All three functions operate on lists of lists of ggplot objects and can # handle NULL objects. # # NOTE: the alignment procedure fails if there is at least one plot with facets! # Transform ggplot objects to gtable objects. # # @param pls [list of (lists of) ggplot object(s)] toGTable = function(pls) { lapply(pls, function(pl) { if (inherits(pl, "ggplot")) { return(ggplot2::ggplot_gtable(ggplot2::ggplot_build(pl))) } if (inherits(pl, "gtable") || is.null(pl)) { return(pl) } return(toGTable(pl)) }) } # Determine maximal left margin width of gtables recursively. # # @param pls [list of (lists of) gtable object(s)] getMaxPlotWidth = function(pls) { do.call(grid::unit.pmax, lapply(pls, function(pl) { if (is.null(pl)) { return(pl) } if (!inherits(pl, "gtable")) { return(getMaxPlotWidth(pl)) } return(pl$widths[2:3]) })) } # Set left margin width of gtables recursively. # # @param pls [list of (lists of) gtable object(s)] # @param pls [list of units] toAlignedGTable = function(pls, max.width) { lapply(pls, function(pl) { if (is.null(pl)) { return(pl) } if (!inherits(pl, "gtable")) { return(toAlignedGTable(pl, max.width)) } pl$widths[2:3] = max.width return(pl) }) } ParamHelpers/R/OptPath_plotEAF.R0000644000176000001440000000671713636346430016165 0ustar ripleyusers#' @title Plots attainment functions for data stored in multiple OptPaths. #' #' @description #' Can be used to plot OptPaths where information for bi-objective #' evaluation was logged for repeated runs of different algorithmic runs. #' Pretty directly calls [eaf::eafplot()]. #' #' @param opt.paths (`list`)\cr #' List of list of `OptPath` objects. First index is the algorithm / major #' variation in the experiment, second index is the index of the replicated #' run. #' @param xlim (`numeric(2)`)\cr #' The x limits (x1, x2) of the plot. #' @param ylim (`numeric(2)`)\cr #' The y limits (y1, y2) of the plot. #' @param ... (any)\cr #' Passed on to [eaf::eafplot()]. #' @note #' We changed the defaults of [eaf::eafplot()] in the following way: The axis #' are labeled by `y.names`, colors are set to our favorite grey values and #' linetypes changed, too. With our colors / linetypes default it is possible #' to distinguish 6 different algorithms. But this can again be overwritten by #' the user. #' @return [`data.frame`] #' Invisibly returns the data passed to [eaf::eafplot()]. #' @export plotEAF = function(opt.paths, xlim = NULL, ylim = NULL, ...) { requirePackages("eaf", why = "plotEAF") # we need a list of lists with optimization pathes assertList(opt.paths, min.len = 1L, types = "list", names = "unique") if (!is.null(xlim)) { assertNumeric(xlim, len = 2L) } if (!is.null(ylim)) { assertNumeric(ylim, len = 2L) } algos = names(opt.paths) y.names = NULL minimize = NULL data = data.frame() for (i in seq_along(algos)) { # extract opt path list for current algorithm a = algos[i] runs = opt.paths[[i]] assertList(runs, types = "OptPath", min.len = 1L) # combine all fronts for this algo + add algo / repl + do some sanity checks fronts = lapply(seq_along(runs), function(j) { run = runs[[j]] df = as.data.frame(getOptPathParetoFront(run), stringsAsFactors = TRUE) cns = colnames(df) if (length(cns) != 2L) { stopf("Must always have 2 objectives in opt path. But found: %i", length(cns)) } if (i == 1L && j == 1L) { y.names <<- cns minimize <<- run$minimize } if (!all(y.names == cns)) { stopf("Must always have the same 2 objectives in opt path: %s (first ones taken). But found here: %s", collapse(y.names), collapse(cns)) } if (!all(minimize == run$minimize)) { stopf("Must always have the same 'minimize' settings for objectives in opt path: %s (first one taken). But found here: %s", collapse(minimize), collapse(run$minimize)) } # add column for algorithm and replication cbind(df, .algo = a, .repl = j, stringsAsFactors = TRUE) }) fronts = do.call(rbind, fronts) data = rbind(data, fronts) } yn1 = y.names[1L] yn2 = y.names[2L] # build parameter list for eafplot function f = as.formula(sprintf("%s + %s ~ .repl", yn1, yn2)) defaults = list( xlab = yn1, ylab = yn2, percentiles = 50, col = c("darkgrey", "darkgrey", "darkgrey", "black", "black", "black"), lty = c("solid", "dashed", "dotdash", "solid", "dashed", "dotdash") ) args = list(...) args = insert(defaults, args) args$data = data args$groups = quote(.algo) args$maximise = !minimize args$xlim = xlim args$ylim = ylim do.call(eaf::eafplot, c(list(f), args)) # due to not so good programming in eafplot the first argument can not be named if it's a formula return(data) } ParamHelpers/R/repairPoint.R0000644000176000001440000000210313633666270015515 0ustar ripleyusers#' Repairs values of numeric and integer parameters out side of constraints. #' #' Clips values outside of box constraints to bounds. #' #' @template arg_parset #' @param x [list]\cr #' List of parameter values. Must be in correct order. #' Values corresponding to non-numeric/integer types are left unchanged. #' @param warn (`logical(1)`)\cr #' Boolean indicating whether a warning should be printed each time a value is repaired. #' Default is `FALSE`. #' @return [list]: #' List of repaired points. #' @export repairPoint = function(par.set, x, warn = FALSE) { assertClass(par.set, "ParamSet") assertList(x) assertFlag(warn) Map(function(par, val) { if (isNumeric(par, include.int = TRUE)) { # repair scalar non-NAs and vectors if (!(length(val) == 1L && is.na(val)) && any(val < par$lower | val > par$upper)) { if (warn) { warningf("Repairing value for %s: %s", par$id, paramValueToString(par, val)) } val = pmax(par$lower, val) val = pmin(par$upper, val) } } return(val) }, par.set$pars, x) } ParamHelpers/NEWS.md0000644000176000001440000001305313636347341013777 0ustar ripleyusers# ParamHelpers 1.14 - Fixes to work with R-4.0.0 # ParamHelpers 1.13 - `trafo` allowed in DiscreteVectorParam. - Removed non-descriptive warning when a param has `NA` set as default. - `generateDesign` rewritten in `R` to avoid random error in C `REAL() can only be applied to a 'numeric', not a 'NULL'`. Function should only be slower if requirements are given in a non vectorized manner. # ParamHelpers 1.12 - improved documentation - speedups # ParamHelpers 1.10 - adapt to irace 2.1 API changes ## new functions - getRequirements - isSpecialValue - getTypeStringsLogical, getTypeStringsCharacter, getTypeStringsAll - isNumericTypeString, isIntegerTypeString, isDiscreteTypeString, isLogicalTypeString, isCharacterTypeString, isVectorTypeString - generateDesignOfDefaults # ParamHelpers 1.9 - Many parameters can now be expressions which can be evaluated later while providing a lookup dictionary. - make*Param now accepts special.vals which are always feasible - getParamLengths, getLower, getUpper, getValues were made S3 to also work on normal Parameter objects ## new functions - evaluateParamExpressions - hasExpression # ParamHelpers 1.8 - plots produced by renderOptPathPlot, plotOptPath are now always nicely aligned - removed soobench from SUGGESTS and removed function extractParamSetFromSooFunction - hasDiscrete: added arg "include.logical" - getParamSet has become a generic - OptPath: it is possible to log non-scalar values under "extras" now by starting the extra-name with a dot. These elements wll not be contained is as.data.frame(opt.path) when converted. - make*Param argument 'requires' now accepts expressions and quote'd expressions. - getParamIds is now S3 and also callable on type "Param" - filterParams: has new arg "check.requires" - isFeasible: new args "use.defaults" and "filter" - trafoValue: slightly robustify arg handling ## new functions - isNumericStrict - getTypeStringsNumeric, getTypeStringsNumericStrict, getTypeStringsInteger, getTypeStringsDiscrete - filterParamsNumeric, filterParamsDiscrete - updateParVals # ParamHelpers 1.7 - dfRowsToList, dfRowToList: added arg enforce.col.types - UntypedParam also got the "tunable" flag # ParamHelpers 1.6 - added new character parameter types, see new functions below - added property 'tunable' to make*Param - isFeasible supports named lists for unordered checks - numeric and numericvector Params and LearnerParams have a new arg 'allow.inf' - filterParams can now filter based on 'ids' and 'tunable' - convertParamSetToIrace: removed argument 'digits' to keep maximum precision of boundaries - added renderOptPathPlot and plotOptPath for plotting of optimization paths. - added plotEAF and plotYTraces to compare singlecrit and bicrit optimization paths. ## new functions - isRequiresOk - plotEAF - plotYTraces - renderOptPathPlot, plotOptPath - makeCharacterParam, makeCharacterVectorParam - isCharacter, hasCharacter # ParamHelpers 1.5 - added constr.clip to print.ParamSet and related internal functions to make prints more readable - getDefaults: new option include.null # ParamHelpers 1.4 - sampleValue(s): 'discrete.names' now only affects discrtete params and not logicals anymore. logical params always result in R data type 'logical' - Vector params (num, int and log) can now have component names - many more OptPath getter methods allow the selection option 'dob' and 'eol' to subset the result ## new functions - getOptPathX - generateRandomDesign # ParamHelpers 1.3 - sampleValue(s): 'discrete.names' now only affects discrtete params and not logicals anymore. logical params always result in R data type 'logical' - Vector params (num, int and log) can now have component names Functions that produce such vector values (e.g. sampleValue or dfRowsToList) will name the components of this vector automatically. The user can also call setValueCNames in his own code. ## new functions - getOptPathCols - setValueCNames - repairPoint # ParamHelpers 1.2 - normal parameters can now have a default value - parameter spaces can now define a forbidden region of infeasibility. all operations on the set respect this, although a few are disallowed and produce an exception. - rewrote generateDesign and dfRowsToList in C to greatly increase speed in the case of dependent parameters - generateDesign and generateGridDesign do not support type conversion anymore. See help page. - generateDesign now ensures that no duplicted settings are produced in rarer cases - Added option to log error messages, execution time and extra info in the optimization path. - slightly change interface of getOptPathY, so one can now return a matrix of multiple measures. - paramValueToString produces better readable output - sampleValue(s) have new option "trafo" - getLower and getUpper have with.nr argument now - getTypes renamed to getParamTypes ## new functions - isNumeric, isDiscrete, isInteger, isLogical - hasNumeric, hasInteger, hasDiscrete, hasLogical - getParamNr - getDefaults - hasTrafo, hasRequires - isForbidden, hasForbidden - generateGridDesign - getOptPathExecTimes, getOptPathErrorMessages - getOptPathParetoFront - getOptPathCol # ParamHelpers 1.1-35 - concept of dependent parameters was introduced (argument "requires") - as.data.frame.OptPath: discretes.as.factor option - all arguments "length" renamed to len ## new functions - convertParamSetToIrace - dfRowToList, dfRowsToList - getOptPathDOB, getOptPathEOL - hasRequires - removeMissingValues # ParamHelpers 1.0-55 - disabled one unreasonable unit test for CRAN - some dependencies are now imports like they should be # ParamHelpers 1.0-54 - First submit to CRAN. ParamHelpers/MD50000644000176000001440000002416714260547430013214 0ustar ripleyusers659479ce441a2de0ffd15dcb5e703a26 *DESCRIPTION 6d62c17754c6c23eb1de160c2004968e *LICENSE cd99a6da61285b73913abec0fd05dbb1 *NAMESPACE 26d9635eee92c8359cc2504759b4bbc4 *NEWS.md 7b66a8547ca9172607e3809b79a85e5b *R/LearnerParam.R d2371bbc84f482fc8c813fdfff9c3ff2 *R/OptPath.R 407c74bf14841cec7519947ee87fbd2e *R/OptPathDF.R 4ef75cf2a080cd44e46e6b2bdaefba58 *R/OptPathDF_as_data_frame.R 3ca41ee81f28fb96640f1bb96a75b1b9 *R/OptPathDF_getter.R 3bca1a14ec8e9f62524b71ce9d62be4f *R/OptPathDF_setter.R 06ed5e5f92a6eb8cd7fff5cc555f0f84 *R/OptPath_getter.R e180d1bc19036878d4b641f0a09ebbb1 *R/OptPath_plotEAF.R 65e905b5296e66f6258effe92e816adf *R/OptPath_plotYTraces.R ad34ecac9515ad745e2a9f59fb5b7f9f *R/OptPath_plotter.R 9024dae19dfd16bc5256acd1d3fb054a *R/OptPath_setter.R 2bb1d6f7b6579a02697fb27d4d19c7c9 *R/ParamSet.R d8f3ad12927d7eaa225a40300611f356 *R/aParam.R 2a0a82d6cc3197f8e870f8a09948d699 *R/checkParamSet.R 89e3359f6c9ba19c7316d09ad848d069 *R/convertDiscrete.R d45d00387959d6b9514a08da5a1f2f6f *R/convertParamSetToIrace.R 165d0b953e127cd9c69c9d161f83d339 *R/convertTypesToCInts.R 31f789de30f54efcec4a7770167808ba *R/dfRowsToList.R d0e4e0ce5506bceb4732e012f5202933 *R/dropParams.R 1295c5e9b3c46d0ecc9798a0fe29e047 *R/evaluateParamExpressions.R ce87bd90d8e7c29b382700ec8dbcddd3 *R/filterParams.R d924eda36b76fcfec786dc010cfc9389 *R/generateDesign.R 8f56ff6fef8aaef9b896d201b6e90945 *R/generateDesignOfDefaults.R 1a29fdf9c0a546beb851ce869904d896 *R/generateGridDesign.R 7e47028a9aeae084df32784c97a1c7b1 *R/generateRandomDesign.R 816338c83f32f06cef722a99b20cfde5 *R/getBounds.R 2eb29b9a06c5aa2db7f99195c24f86c9 *R/getDefaults.R d34191a8a6616f63cd5587e2e7dfe6b4 *R/getParamIds.R c234e388f56181ae5bd243fe60f3b873 *R/getParamLengths.R 56a2711eea5ac7ea076595c306fc7bf4 *R/getParamNr.R 9f079c346504c761c6e3b5ab9d950f58 *R/getParamSet.R d8f2fd2717b33786ff64a6510fb213ba *R/getParamTypeCounts.R da282b9bf042f3f7d92187881601db17 *R/getParamTypes.R 84933ed3f5184ebae96153a32bdb86aa *R/getRequiredParamNames.R 10c7727caadc7eebefaaccae46140fe3 *R/getRequirements.R 49d69ce15741d11f5d4ae5d84af1e94d *R/getTypeStrings.R 2ca839ce3b194800e8cb303f63298d36 *R/hasExpression.R 4314bcc23aace0d0f241b760821db4c1 *R/hasFiniteBoxConstraints.R 7ae41506886f2f26cba23c28c86e3d11 *R/hasForbidden.R 6618740d7e8dfa826b1dab862ff7ec82 *R/hasRequires.R c4ddff6edcbad5c06d9024fe53e83284 *R/hasTrafo.R b75eafcbcb756d87569a76d8711e004f *R/hasType.R d3395acde8b638f554690a3c8057e62e *R/isFeasible.R 1068ed2a736baac3b371747dd60dc1ce *R/isForbidden.R 843cd1faca6e0ab757690b22c7553793 *R/isRequiresOk.R 9d4f2e8a03d542bacf1c371027d06535 *R/isSpecialValue.R a66cbf9b9717f0eec763d2c5232b7434 *R/isType.R 28b3f8680cfe0633af5fba24d451bf22 *R/isTypeString.R ae15aed569541a453528a93eeec82625 *R/isVector.R 7e7edb0a272366110c65c90af698abe3 *R/listToDfOneRow.R f73d3d4aeec4e0cfbe9f59ea1cd52a7f *R/makeLearnerParamFuns.R 64674a98520cc73c7878fc3423624def *R/makeParamFuns.R 560b52289b49dfde76381ab4914ed8e2 *R/paramValueToString.R 8087a8295d6c0bf96c1b1d7d37489231 *R/removeMissingValues.R 1bde90e3c42c739e0f471650b9ef9600 *R/renderOptPathPlot.R 1c8724972d5254bfbfc6f69a46a65023 *R/renderOptPathPlot_helpers.R 663d6fc64f506135361ab1539be748a6 *R/renderOptPathPlot_workers.R d063288413dfd635fe8b45b0e0a98145 *R/repairPoint.R 5cc516b9f23cd978f30727c8600989ba *R/sample.R 0a7974d5b1e0cc2c6ea9cc6287ee39e5 *R/setValueCNames.R 717512938f1eb229b2b06904e4b8cbdb *R/trafo.R 4f3eaa07f9217d05a9e6e87b83165d96 *R/updateParVals.R 3ed01fbe9db2c9342578cb04e4c78a9b *R/utils.R e54402ad4a77ab7ee61f5494f100b963 *R/zzz.R 37ff1801a409dacb00b7dac6144d9c2d *man/LearnerParam.Rd e85a47cca531c973d1a55608d7b9e246 *man/OptPath.Rd dbf0ccc6bd64bd319107839578893f08 *man/Param.Rd 1bfd30f6077c666d7ee21e2ab20ce1b6 *man/addOptPathEl.Rd e8dca8bd456265b6ba2478d3c7de9077 *man/as.data.frame.OptPathDF.Rd 8e2c8ec8d138b604cfda4fc77d57b560 *man/checkParamSet.Rd 77eb45b65f015686e7e3adebb006a651 *man/convertParamSetToIrace.Rd 18db72a8c226d6693842266633bd04ea *man/dfRowsToList.Rd 13c0723d3ab2b30d9bcf7fd950808d12 *man/discreteNameToValue.Rd 4b1035c7cc4a36542f5990d17075ecfc *man/discreteValueToName.Rd e8f21e5c2cd7bd9b8365b21856676df9 *man/dropParams.Rd ae224adecc1f81e4ae1784eb2fcfa4b5 *man/evaluateParamExpressions.Rd effe96d54bead04806c7f9b803601b4a *man/filterParams.Rd f9c1283afd216d67961217cfa1366559 *man/generateDesign.Rd eee62bc85b11d02b98f54b94f4dd8157 *man/generateDesignOfDefaults.Rd 441fe78dc5ebcb4cdf1c6eb2eb47692c *man/generateGridDesign.Rd 1006e0d5d4cd8e082b0bfdb4bdb8c326 *man/generateRandomDesign.Rd e3839fc1445449c0ff5ad1942bf4ebca *man/getDefaults.Rd 3594d7583915c6685627f31176a94638 *man/getLower.Rd a9cc528f3530445bf50b372d8a4ae1cb *man/getOptPathBestIndex.Rd e7c2e090d331628306ca6cf6a193800b *man/getOptPathCol.Rd bb75fd1285f2457d8ed0e556cc440248 *man/getOptPathCols.Rd 6962fc83565158e7c55e22978b6b88cd *man/getOptPathDOB.Rd 7c7b5e87cb3af7ec32d7e5b73d42cdf6 *man/getOptPathEOL.Rd 5d78b240761003f2e4ecb715e13183c5 *man/getOptPathEl.Rd 71ff5784efa8d003e86378fea781b6fe *man/getOptPathErrorMessages.Rd 401a91c1e99e0b82c0fc151fc0ec0242 *man/getOptPathExecTimes.Rd 1f1d7dbd8b467af4305b078083076492 *man/getOptPathLength.Rd f4f1463ea74f90f33a68d66169b52511 *man/getOptPathParetoFront.Rd a96160e05d00e9b4b717e8bdee95b7f0 *man/getOptPathX.Rd 7e2b3044eb0ec0356783488bed6c41d9 *man/getOptPathY.Rd 73c4b0a08b7f7739b15d53ffdc0f698e *man/getParamIds.Rd 9cb3030260e5901364f78bebc871de69 *man/getParamLengths.Rd 0b6cb98702ed81e5f2d229adad6b090b *man/getParamNr.Rd 87f3579d643169696294a9fe19d342bc *man/getParamSet.Rd 26eac96ea6f578ac18af528f1be5d219 *man/getParamTypeCounts.Rd 82a281b457eeca354ffd0e7b4da4f6b6 *man/getParamTypes.Rd 4a222c4385594ba448cc9d13136fbe50 *man/getRequirements.Rd 6f7dc5ca442b82fe2665cee82d106296 *man/getTypeStrings.Rd 5f83cc5af2692fcaee3ab6144441403f *man/hasExpression.Rd e19cad6229e913fbe0131aefd925b7cc *man/hasFiniteBoxConstraints.Rd 35050d6f2f0bf689b5b3fdf135b33873 *man/hasForbidden.Rd 582029a92d82de013cb6ea75f1dd71aa *man/hasRequires.Rd 43c969d76acc9cd0dfee928f2fcd4178 *man/hasTrafo.Rd 1cf2ce9f4ac6324817898138f7287dbf *man/hasType.Rd afe0714984bbe83e6532212e44d6eba3 *man/isEmpty.Rd 5ad0fdddaec95753c075f6bf0d4d8d17 *man/isFeasible.Rd 1c80d555cc65a127ceb8803470aa4425 *man/isForbidden.Rd c70588d6f2bc1a3d16378391354c7039 *man/isRequiresOk.Rd 6fddf781a02d08d8fe9059a17de3aaa6 *man/isSpecialValue.Rd 2d6a82f77cdebb8f97718509032ae3da *man/isType.Rd 0931bec166bc26d62392f5da10281f4c *man/isTypeString.Rd 4fece3dd393a827ecc45b51ad8b8f747 *man/isVector.Rd b3340f1604b409e65a5775ae486f27ae *man/listToDfOneRow.Rd 21b76ed7a0f9de2ebb78ee5e89019d63 *man/makeParamSet.Rd b0d25ac4f91e105c4e4c259d38f46c68 *man/paramValueToString.Rd a9908ff27e100789ad303204d329d659 *man/plotEAF.Rd 1fc082c8eebb67b5f70974ddce02ab3e *man/plotOptPath.Rd 25ab6001ce2621660a6fc6720436ead6 *man/plotYTraces.Rd bd5033f7e277dd5bf6fcb3b7e0939212 *man/removeMissingValues.Rd 34202b1e88325837896ef555568cd057 *man/renderOptPathPlot.Rd f0c819174674069227e5dd9c93c5d2cc *man/renderYTraces.Rd 497cb777a2c14d396082daae5fcdf6d3 *man/repairPoint.Rd 47435d93c8b9904dd8ccbb19a4ce2f46 *man/sampleValue.Rd 43df522e75cd6a907792bea77d8e42b3 *man/sampleValues.Rd ee123668a6b98a8d9226344106accf7e *man/setOptPathElDOB.Rd 659fe5a0db624cab5887ddc70d4fc500 *man/setOptPathElEOL.Rd 69910b5b5c6ce146df484c10c3965bef *man/setValueCNames.Rd 83fa515b5be78760417fa5746f5a954c *man/trafoOptPath.Rd 3c10c67f8fc96707a080fe4d57bce507 *man/trafoValue.Rd d5b882163900b0f3ef402ebc06d54366 *man/updateParVals.Rd 7ad010d3392781d3f82ffad741af6a76 *src/c_dfRowsToList.c 96b3056a7b4def6007172ecff32e738f *src/init.c 7d247dc5379c71c326956bd2c10b3b28 *tests/run-all.R 4dd8da7b525b1fd255a514b0f57fd984 *tests/testthat/Rplots.pdf 5c2824a8ec0dd6207be1b0eead24b969 *tests/testthat/helper_zzz.R 2492625465e84b4da8dd78598e0a0cd3 *tests/testthat/test_LearnerParam.R a5692236ce56d855be8b2735abee19b2 *tests/testthat/test_OptPath.R fc4068e6c6fa85dcbae170260e778339 *tests/testthat/test_Param.R a70184dd697e1cebb4b1aebfeb03a51a *tests/testthat/test_ParamSet.R cc80d409f99c8912a5c28780716ba0df *tests/testthat/test_cnames.R 69d06b3ed480e0be665d08c1eb157675 *tests/testthat/test_convertDiscrete.R 6fb50b89f84f9afb4ca4eff98cd5e908 *tests/testthat/test_convertParamSetToIrace.R bd9b81a4e8b9ec6ee72b0d1e71990183 *tests/testthat/test_dfRowToList.R 2dc5f315b3cf14ba2fe6f7d8170de1ad *tests/testthat/test_dropParams.R 768a302d845503c5483dcc6256d8e4da *tests/testthat/test_evaluateParamExpressions.R d77751092b704bf8387087037d48e54d *tests/testthat/test_filterParams.R 79c696049efee6e7fe864ac35965cb64 *tests/testthat/test_forbidden.R 9b65419edf86025bdc7797ae04d41e3f *tests/testthat/test_generateDesign.R faa0613b48423d1f1b631a9a07547085 *tests/testthat/test_generateDesignOfDefaults.R 5bc1362feef9428f7024507d16403d81 *tests/testthat/test_generateGridDesign.R fcff861dbb859f27a889bdb03f7327fd *tests/testthat/test_generateRandomDesign.R 0e00445dc63d14869f42d33c3a430047 *tests/testthat/test_getDefaults.R 77fb3f676858d9f2b0f88a5a35077ecf *tests/testthat/test_getParamNr.R 400bf7d864b7931501e0ef07405dd153 *tests/testthat/test_getParamTypeCounts.R d1d7550e963cad551375bf835c86e456 *tests/testthat/test_getParamTypes.R b855c8d700fcaee898c0efcb98c33982 *tests/testthat/test_getRequiredParamNames.R acc0e49c5d35db2e209baa11d942e7c8 *tests/testthat/test_getRequirements.R 1d5d795790a51106bca662ed5d4b8442 *tests/testthat/test_hasExpression.R 03738e8b38f64a66e83aeeabc4c19705 *tests/testthat/test_hasFiniteBoxConstraints.R edb448edbf1007bdd1a15e8db96446f2 *tests/testthat/test_hasIsType.R 492d2b566092bcb0c08a33dbfc9b9664 *tests/testthat/test_hasRequires.R 054d42295b5fa82cca703b574a77f6b3 *tests/testthat/test_isFeasible.R 66742ba7449a55794f6fba59e3d03eed *tests/testthat/test_isSpecialValue.R cd4063e88a67f217f15fabf0098933ac *tests/testthat/test_isVector.R 856935ca5211a27e106d33eb3b837ffa *tests/testthat/test_paramValueToString.R 6bfe0e97c65c2f1087b700de9a199cb4 *tests/testthat/test_plotEAF.R 04d13a44aa43c99f9da4e1ba50bac3b0 *tests/testthat/test_plotYTrace.R bfa28a66c1b0de9096d71e625f4051c8 *tests/testthat/test_renderOptPathPlot.R a8160bd26188d83a3ad6f0e960af0d7b *tests/testthat/test_repairPoint.R 632df43a0ea75905275cc2f5782b9e6c *tests/testthat/test_sample.R e5e2aea03a3673f106a534d83af86fa0 *tests/testthat/test_trafo.R 285a1987b554767657ede2a87ed329f6 *tests/testthat/test_updateParVals.R