#' @title Starts SMAC (alternative)
#' @description Starts SMAC on the given function, with the given scenario and the given params.
#' @param fun [\code{smoof_function}]
#' NOTE: If the \code{par.set} of the smoof function has trafos they will be invisible for SMAC and only be applied after SMAC proposed values within the untransforemd range.
#' @param scenario [\code{list}] \cr
#' scenario description
#' @param params [\code{character}] \cr
#' Params in pcs format. Default is \code{\link{as.pcs}(getParamSet(fun))}.
#' If \code{params} are supplied the trafos of the par.set of the smoof function will not be applied.
#' @param path.to.smac [\code{character(1)}] \cr
#' The directory where the smac binary is located.
#' All intermediate files will be saved there.
#' @param cl.args [\code{list}] \cr
#' CL arguments that should be passed when calling \code{./smac}.
#' @param id.smac.run [\code{character(1)}] \cr
#' You might want to overrride the automaticly generated ID to do restarts or parallel optimizations on the exact same scenario.
#' @param cleanup [\code{logical(1)}] \cr
#' Should all files be deleted after the run?
#' @param par.id [\code{integer(1)}] \cr
#' For parallel usage on the same id.smac.run this helps to specify the which parallel run we are in.
#' Only the call with \code{par.id = 1} will write the enviroment to the disk.
#' @examples
#' \dontrun{
#' scenario = list("use-instances" = "false", runObj = "QUALITY", numberOfRunsLimit = 5)
#' res = rsmac(makeBraninFunction(), scenario = scenario)
#' best.idx = getOptPathBestIndex(res)
#' getOptPathEl(res, best.idx)
#' as.data.frame(res)
#' }
#' @return \link[ParamHelpers]{OptPath}
#' @export
rsmac = function(fun, scenario, params = NULL, path.to.smac = "~/bin/smac", cl.args = list(), id.smac.run = NULL, cleanup = TRUE, par.id = 1) {
assertClass(fun, "smoof_function")
assertList(scenario)
assertFlag(cleanup)
assertCount(par.id)
if (par.id > 1 && is.null(id.smac.run)) {
stop("For a par.id > 1 you have to supply a id.smac.run!")
}
if (par.id > 1 && cleanup) {
stop("Parallel runs can not run with automatic cleanup!s")
}
if (is.null(params)) {
pcs = as.pcs(obj = getParamSet(fun))
} else {
pcs = assertCharacter(params)
if (hasTrafo(getParamSet(fun))) {
warning("The par.set of the smoof function has a transformation. Those will be ignored because pcs params were supplied.")
}
}
path.to.smac = path.expand(path.to.smac)
assertFileExists(file.path(path.to.smac, "smac"))
# generate unqiue scenario name and sub folders
if (is.null(id.smac.run)) {
id.smac.run = stri_paste(
getID(fun),
"_",
(sample(999999, size = 1) + as.integer(Sys.time()) + Sys.getpid()) %% 999999)
}
assertString(id.smac.run)
rsmac.dir = file.path(path.to.smac, sprintf("rsmac_%s", id.smac.run))
if (par.id > 1) waitUntilExists(rsmac.dir) else dir.create(rsmac.dir)
scenario.name = sprintf("rsmac-scenario-%s", id.smac.run)
scenario.file = file.path(rsmac.dir, sprintf("%s.txt", scenario.name))
# write scenario file
default.scenario = list(
"pcs-file" = file.path(rsmac.dir, "rsmac-params.pcs"),
"algo" = sprintf("%s -id.smac.run %s", file.path(rsmac.dir, "smac_wrapper.R"), id.smac.run)
)
scenario = insert(default.scenario, scenario)
if (par.id > 1)
waitUntilExists(scenario.file)
else {
writeLines(
stri_paste(names(scenario), scenario, sep = " = "),
con = scenario.file)
}
# deal with CL args
default.cl.args = list(
"scenario-file" = scenario.file,
"initial-incumbent" = "RANDOM",
"num-validation-runs" = 0
)
cl.args = insert(default.cl.args, cl.args)
assertList(cl.args, min.len = 1L, names = "named")
# write params file
params.file = file.path(rsmac.dir, "rsmac-params.pcs")
if (par.id > 1) waitUntilExists(params.file) else writeLines(pcs, con = params.file)
# write rscript to be called from smoof that wraps the
template.file = system.file("templates/smac_wrapper.R", package = "rsmac")
script.file = file.path(rsmac.dir, "smac_wrapper.R")
if (par.id > 1)
waitUntilExists(script.file)
else {
file.copy(template.file, script.file, overwrite = TRUE)
system(sprintf("chmod +x %s", file.path(rsmac.dir, "smac_wrapper.R")))
}
# write enviroment for the smac_wrapper
enviroment.file = file.path(rsmac.dir, "enviroment.RData")
if (par.id > 1) waitUntilExists(enviroment.file) else save.image(enviroment.file)
# write register for the smac_wrapper
register = list(
packages = names(sessionInfo()$otherPkgs),
fun = fun,
apply.trafo = is.null(params)
)
register.file = file.path(rsmac.dir, "register.rds")
if (par.id > 1) waitUntilExists(register.file) else writeRDS(register, register.file)
# write initial dob file
init.dob.file = file.path(rsmac.dir, sprintf("dob_%.6i.rds", 0))
if (par.id > 1) waitUntilExists(init.dob.file) else writeRDS(0, init.dob.file)
# take care of cleanup
if (cleanup) {
on.exit({
unlink(rsmac.dir, recursive = TRUE)
unlink(file.path(path.to.smac, "smac-output", scenario.name), recursive = TRUE)
}, add = TRUE)
}
# start smac
cl.output.file = file.path(rsmac.dir, sprintf("rsmac-output-%i.txt", par.id))
command = sprintf(
"(cd %s && ./smac --%s > %s)",
path.to.smac,
stri_paste(names(cl.args), cl.args, collapse = " --", sep = " "),
cl.output.file)
call.res = system(command, wait = TRUE, ignore.stdout = FALSE, ignore.stderr = FALSE, intern = FALSE)
if (call.res != 0) {
stopf("Call of '%s' ended with ERROR CODE %s", command, as.character(call.res))
}
# Write OptPath
opt.path = makeOptPathDF(par.set = getParamSet(fun), y.names = "y", minimize = shouldBeMinimized(fun), include.exec.time = TRUE, include.extra = TRUE, add.transformed.x = hasTrafo(getParamSet(fun)) && !is.null(params))
opt.el.files = list.files(
path = rsmac.dir,
pattern = sprintf("res_\\d+_\\d+\\.rds"),
full.names = TRUE)
opt.els = lapply(opt.el.files, readRDS)
for (opt.el in opt.els) {
addOptPathEl(op = opt.path, x = opt.el$x, y = opt.el$y, dob = opt.el$dob, exec.time = opt.el$exec.time, extra = opt.el$extras)
}
res = opt.path
attr(res, "rsmac.dir") = rsmac.dir
attr(res, "par.id") = par.id
return(res)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.