The package randomsearch optimizes a given smoof function. Use makeSingleObjectiveFunction()
to wrap any function into a smoof function. It can make use of parallel resources through prallelMap. randomsearch has three internal operating modes:
max.evals
is defined as termination criterion. max.execbudget
and target.fun.value
have to be NULL
.max.execbudget
or target.fun.value
have been set and parallelStart
has been called without defined level
or with level = randomsearch.feval
. In this mode par.jobs
(defaults to parallelGetOptions()$settings$cpus
) instances are started. Each instance conducts a random search until the termination criterion is met. The instances communicate using a shared folder (par.dir = ~/.randomsearch/
).max.execbudget
or target.fun.value
have been set. Note, that this introduces an overhead to fast.parallel even without parallelization because the termination criterion is checked after each evaluation.Simple usage with functions that use a vector as input:
fun = function(x) x[1]^2 + sin(x[2])
res = randomsearch(fun, lower = c(-1, -1), upper = c(2,2), minimize = TRUE, max.evals = 30)
rs = summary(res)
rs$best.x
## $x
## [1] -0.2617368 -0.8738214
## y
## -0.6982813
## x1 x2 y dob eol exec.time
## 25 -0.2020821 1.5734831 1.04083356 25 NA 0
## 26 -0.8625065 0.3266002 1.06474229 26 NA 0
## 27 1.3967745 -0.6343022 1.35836350 27 NA 0
## 28 0.6828440 -0.3804058 0.09497854 28 NA 0
## 29 -0.6174050 1.2599236 1.33325597 29 NA 0
## 30 1.6851361 0.1233883 2.96275907 30 NA 0
For usage with more complicated search spaces you have to define a smoof function. This allows you to tune over discrete parameters and even hierarchical parameter sets like in this example. Here the parameter y
is only active if a==a2
.
fun = function(x) {
if (x$a == "a1") {
x$x^2
} else if (x$a == "a2") {
sin(x$x * x$z) + 1
}
}
obj.fun = makeSingleObjectiveFunction(
fn = fun,
par.set = makeParamSet(
makeDiscreteParam("a", values = c("a1", "a2")),
makeNumericParam("x", lower = -3, upper = 3),
makeNumericParam("z", lower = 0, upper = 2, requires = quote(a == "a2"))
),
minimize = TRUE,
has.simple.signature = FALSE
)
res = randomsearch(obj.fun, max.evals = 30)
rs = summary(res)
rs$best.x
## $a
## [1] "a2"
##
## $x
## [1] -2.430956
##
## $z
## [1] 0.7679393
## y
## 0.04349791
## a x z y dob eol exec.time
## 25 a2 1.4224664 1.0422715 1.9961129 25 NA 0
## 26 a2 1.9308328 1.5725631 1.1050422 26 NA 0
## 27 a2 -0.3634108 0.6234044 0.7753811 27 NA 0
## 28 a1 -2.9371973 NA 8.6271281 28 NA 0
## 29 a2 -1.6130293 0.4781999 0.3028959 29 NA 0
## 30 a1 -1.5256579 NA 2.3276321 30 NA 0
Note: randomsearch()
detects a multi-objective optimization by the length of the minimize
vector.
obj.fun = function(x) c(x[1]^2 + sin(x[2]), cos(x[1]))
res = randomsearch(obj.fun, lower = c(-1, -1), upper = c(2,2), minimize = c(TRUE, TRUE), max.evals = 30)
summary(res)
## Randomsearch Result:
## Multiobjective Search Pareto Front
## y_1 y_2 x1 x2
## 1 -0.2266606 0.88324220 -0.4880643 -0.48348476
## 3 -0.2274047 0.94463890 0.3343040 -0.34602799
## 4 -0.2309050 0.98662663 0.1637271 -0.26065302
## 6 0.1701176 0.75456461 0.7158059 -0.34932171
## 8 0.3583286 0.62947484 0.8899192 -0.44851453
## 10 1.0262387 0.58171931 0.9499555 0.12414187
## 14 1.0618198 0.43129294 1.1248710 -0.20494658
## 15 1.1604827 0.34270358 1.2210031 -0.33669119
## 16 2.2456680 0.05147028 1.5193033 -0.06265551
## 21 3.3156845 -0.05322554 1.6240470 0.74525030
## 22 3.6721829 -0.23881557 1.8119423 0.39959811
## 29 4.5873757 -0.37660278 1.9569227 0.85997993
Of course multi-objective optimization works with smoof functions as well. A multi-objective smoof function is constructed as follows:
You can simply augment the results of a random search with additional random search results by converting the old result to a data.frame
and use it as an input for a new random search.
fun = function(x) x[1]^2 + sin(x[2])
res = randomsearch(fun, lower = c(-1, -1), upper = c(2,2), minimize = TRUE, max.evals = 10)
summary(res)
## Randomsearch Result:
## Eval no.: 9
## x: x=-0.228,-0.335
## y: -0.276282
des = as.data.frame(res)
res = randomsearch(fun, lower = c(-1, -1), upper = c(2,2), minimize = TRUE, max.evals = 1000, target.fun.value = -0.4)
summary(res)
## Randomsearch Result:
## Eval no.: 243
## x: x=-0.0328,-0.996
## y: -0.8384554