Skip to content

Commit

Permalink
Merge pull request #188 from mlr-org/fix167_shouldTerminate
Browse files Browse the repository at this point in the history
refactor shouldTerminate
  • Loading branch information
berndbischl committed Feb 17, 2016
2 parents 2ac0ce0 + 83816b0 commit 87b9257
Show file tree
Hide file tree
Showing 10 changed files with 70 additions and 44 deletions.
11 changes: 10 additions & 1 deletion R/MBOResult.R
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,16 @@
#' Includes all evaluated points and additional information as documented in \link{mbo_OptPath}.
#' You can convert it via \code{as.data.frame}.}
#' \item{resample.results [List of \code{\link[mlr]{ResampleResult}}]}{List of the desired \code{resample.results} if \code{resample.at} is set in \code{makeMBOControl}.}
#' \item{final.state [\code{character}] The final termination state. Gives information why the optimization ended}
#' \item{final.state [\code{character}] The final termination state. Gives information why the optimization ended. Possible values are
#' \describe{
#' \item{term.iter}{Maximal number of iterations reached.}
#' \item{term.time}{Maximal running time exceeded.}
#' \item{term.exectime}{Maximal execution time of function evaluations reached.}
#' \item{term.yval}{Target function value reached.}
#' \item{term.fevals}{maximal number of function evaluations reached.}
#' \item{term.custom}{Terminated due to custom, user-defined stopping condition.}
#' }
#' }
#' \item{models [List of \code{\link[mlr]{WrappedModel}}]}{List of saved regression models if \code{store.model.at} is set in \code{makeMBOControl}. The default is that it contains the model generated after the last iteration.}
#' \item{control [\code{MBOControl}] Control object used in optimization}
#' }
Expand Down
11 changes: 9 additions & 2 deletions R/OptState.R
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,15 @@ NULL
# @param opt.result \code{OptResult} \cr
# Pointer to the OptResult Object.
# @param state \code{character(1)} \cr
# Tells us in what state we are in text. So far we know: init, iter,
# iter.exceeded, time.exceeded, exec.time.exceeded, target.fun.value.reached, manual.exceeded
# Tells us in what state we are in text. So far we know:
# init - right after iniitilization of mbo
# iter - within an iteration
# term.iter - maximal number of iterations reached
# term.time - maximal running time exceeded
# term.exectime - maximal execution time reached
# term.yval - target fun value reached
# term.fevals - maximal number of function evaluations reached
# term.custom - terminated due to custom stopping condition
# @param opt.path \code{OptPath} \cr
# Here we keep the opt.path. It delivers the data for the tasks and other usefull information.
# @param time.last.saved \code{POSIXct} \cr
Expand Down
21 changes: 14 additions & 7 deletions R/OptState_getter.R
Original file line number Diff line number Diff line change
Expand Up @@ -93,21 +93,23 @@ getOptStateFinalPoints = function(opt.state, unify = FALSE) {
list(
x = best$x,
y = as.numeric(best$y),
best.ind = final.index)
best.ind = final.index
)
} else {
inds = getOptPathParetoFront(opt.path, index = TRUE)
pareto.set = lapply(inds, function(i) getOptPathEl(opt.path, i)$x)
if (unify) {
list(
x = do.call(rbind.data.frame ,pareto.set),
y = getOptPathParetoFront(opt.path),
best.ind = inds)
best.ind = inds
)
} else {
list(
pareto.front = getOptPathY(opt.path)[inds, , drop = FALSE],
pareto.set = pareto.set,
inds = inds
)
)
}
}
}
Expand All @@ -120,10 +122,15 @@ getOptStateTermination = function(opt.state) {
terminate = shouldTerminate.OptState(opt.state)
# update only if termination condition is met
if (terminate$term) {
# custom stopping conditions have no code. We assign 5 here manually, which
# means manual.exceeded (see getTerminateChars(...))
code = if (is.null(terminate$code)) 6L else terminate$code
setOptStateState(opt.state, getTerminateChars(code))
setOptStateState(opt.state, terminate$code)
}
terminate
}

getOptStateValidStates = function() {
c("init", "iter", getOptStateValidTerminationStates())
}

getOptStateValidTerminationStates = function() {
c("term.iter", "term.time", "term.exectime", "term.yval", "term.feval", "term.custom")
}
2 changes: 1 addition & 1 deletion R/OptState_setter.R
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ setOptStateTimeUsed = function(opt.state, time.used = NULL, time.add = NULL) {
}

setOptStateState = function(opt.state, state) {
#assertSubset(state, c("init", "iter", getTerminateChars()))
assertSubset(state, getOptStateValidStates())
opt.state$state = state
invisible()
}
4 changes: 2 additions & 2 deletions R/mboFinalize.R
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ mboFinalize = function(file) {
assertCharacter(file, len = 1L)
opt.state = loadOptState(file)
state = getOptStateState(opt.state)
if (state %in% getTerminateChars()) {
if (state %in% getOptStateValidTerminationStates()) {
warningf("Optimization ended with %s. No need to finalize Simply returning stored result.", state)
return(getOptResultMboResult(getOptStateOptResult(opt.state)))
}
setOptStateState(opt.state, getTerminateChars("manual"))
setOptStateState(opt.state, "term.custom")
mboFinalize2(opt.state)
}

Expand Down
22 changes: 5 additions & 17 deletions R/shouldTerminate.R
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,14 @@ shouldTerminate.OptState = function(opt.state) {
for (stop.cond in stop.conds) {
stop.obj = stop.cond(opt.state)
if (stop.obj$term) {
# if user-defined stopping condition is active, set the code by hand
if (is.null(stop.obj$code)) {
stop.obj$code = "term.custom"
}
return(stop.obj)
}
}

# "fallback"
return(list(term = FALSE, message = NA_character_, code = 0L))
}

# This function returns all the character which lead to an termination
# of the MBO Iteratio if x == NULL, otherwise the representative reason
# according to the number returned in shouldTerminate()
getTerminateChars = function(x = NULL) {
final.states = c(iter = "iter.exceeded", time = "time.exceeded",
exec.time = "exec.time.exceeded", target = "target.fun.value.reached",
evals = "max.evals.reached", manual = "manual.exceeded")
if (is.null(x)) {
return(final.states)
} else if (x == 0) {
return("iter")
} else {
return(as.character(final.states[x]))
}
return(list(term = FALSE, message = NA_character_, code = NA_character_))
}
14 changes: 8 additions & 6 deletions R/term_conds.R
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
# and returns a list with the following three components
# * term: logical indicating whether the stopping condition is met.
# * message: String indicating the reason for termination.
# * code: integer code of stopping condition (only for build-in stopping conditions!)
# * code: short character code of stopping condition (only for build-in stopping conditions!)
# Possible value are term.exectime, term.time, term.feval, term.yval. Besides,
# term.custom is assigned internally for custom, user-made stopping conditions.

# @title
# Maximum iteration stopping condition.
Expand All @@ -19,7 +21,7 @@ makeMBOTerminationMaxIter = function(max.iter) {
iter = getOptStateLoop(opt.state)
term = iter > max.iter
message = if (!term) NA_character_ else sprintf("Maximum number of iterations %i reached with.", max.iter, iter)
return(list(term = term, message = message, code = 1L))
return(list(term = term, message = message, code = "term.iter"))
}
}

Expand All @@ -35,7 +37,7 @@ makeMBOTerminationMaxBudget = function(time.budget) {
time.used = as.numeric(getOptStateTimeUsed(opt.state), units = "secs")
term = (time.used > time.budget)
message = if (!term) NA_character_ else sprintf("Time budged %f reached.", time.budget)
return(list(term = term, message = message, code = 2L))
return(list(term = term, message = message, code = "term.time"))
}
}

Expand All @@ -53,7 +55,7 @@ makeMBOTerminationMaxExecBudget = function(time.budget) {

term = (time.used > time.budget)
message = if (!term) NA_character_ else sprintf("Time budged %f reached.", time.budget)
return(list(term = term, message = message, code = 3L))
return(list(term = term, message = message, code = "term.exectime"))
}
}

Expand All @@ -75,7 +77,7 @@ makeMBOTerminationTargetFunValue = function(target.fun.value) {
current.best = getOptPathEl(opt.path, getOptPathBestIndex((opt.path)))$y
term = (current.best * opt.dir <= target.fun.value * opt.dir)
message = if (!term) NA_character_ else sprintf("Target function value %f reached.", target.fun.value)
return(list(term = term, message = message, code = 4L))
return(list(term = term, message = message, code = "term.yval"))
}
}

Expand All @@ -92,6 +94,6 @@ makeMBOTerminationMaxEvals = function(max.evals) {
evals = getOptPathLength(opt.path)
term = (evals >= max.evals)
message = if (!term) NA_character_ else sprintf("Maximal number of function evaluations %i reached.", max.evals)
return(list(term = term, message = message, code = 5L))
return(list(term = term, message = message, code = "term.feval"))
}
}
11 changes: 10 additions & 1 deletion man/MBOSingleObjResult.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 8 additions & 4 deletions man/setMBOControlTermination.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions tests/testthat/test_stopping_criteria.R
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,21 @@ test_that("stopping criteria works", {
ctrl = setMBOControlTermination(ctrl, iters = iters, time.budget = time.budget)
or = mbo(f, design = design, learner = learner, control = ctrl)

expect_equal(or$final.state, "time.exceeded")
expect_equal(or$final.state, "term.time")

# target fun value
ctrl = makeMBOControl()
ctrl = setMBOControlTermination(ctrl, iters = iters, target.fun.value = target.fun.value)
or = mbo(f, design = design, learner = learner, control = ctrl)

expect_equal(or$final.state, "target.fun.value.reached")
expect_equal(or$final.state, "term.yval")
expect_less_than(or$y, target.fun.value)

# maximal number of target function evaluations
ctrl = makeMBOControl()
ctrl = setMBOControlTermination(ctrl, iters = iters, max.evals = max.evals)
or = mbo(f, design = design, learner = learner, control = ctrl)

expect_equal(or$final.state, "max.evals.reached")
expect_equal(or$final.state, "term.feval")
expect_equal(getOptPathLength(or$opt.path), max.evals)
})

0 comments on commit 87b9257

Please sign in to comment.