Skip to content

Commit

Permalink
Fix #76: Completely new implementation of recovery.
Browse files Browse the repository at this point in the history
  • Loading branch information
MLopez-Ibanez committed Dec 25, 2024
1 parent ccb5c1f commit a2bb7d8
Show file tree
Hide file tree
Showing 15 changed files with 701 additions and 415 deletions.
6 changes: 6 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,18 @@

## Major breaking changes

* Recovery (`--recover-file`) has been completely re-implemented. This
version of irace cannot recover files generated by previous versions and
vice versa.

## New features and improvements

* `psRace()` gains a `psrace_logFile` argument to avoid overwriting `scenario$logFile`.

## Fixes

* Fix #76: Recovery (`--recover-file`) is working again with a completely new implementation.

* Fixed documentation of `psRace()`.

* Fix `psRace()` not saving `psrace_log` in `scenario$logFile`.
Expand Down
4 changes: 4 additions & 0 deletions R/aaa.R
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,7 @@ update_package_version <- function()
update_package_version()
# We define this tentatively to avoid: undefined exports: irace_version
irace_version <- "unknown"

.irace_tolerance <- sqrt(.Machine$double.eps)
.irace_minimum_saving_time <- 60 # seconds

410 changes: 198 additions & 212 deletions R/irace.R

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions R/irace_summarise.R
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ irace_summarise <- function(iraceResults)
if (is.null(version))
version <- iraceResults$irace.version

# Here to support older versions of irace.
time_targetrunner <- iraceResults$state$recovery_info$timeUsed
if (is.null(time_targetrunner))
time_targetrunner <- iraceResults$state$timeUsed
Expand Down
4 changes: 1 addition & 3 deletions R/psRace.R
Original file line number Diff line number Diff line change
Expand Up @@ -225,8 +225,7 @@ psRace <- function(iraceResults, max_experiments, conf_ids = NULL, iteration_eli
elitist_new_instances = 0L)

elite_configurations <- extractElites(raceResults$configurations,
nbElites = race_state$recovery_info$minSurvival,
debugLevel = scenario$debugLevel)
nbElites = race_state$minSurvival, debugLevel = scenario$debugLevel)
irace.note("Elite configurations (first number is the configuration ID;",
" listed from best to worst according to the ",
test.type.order.str(scenario$testType), "):\n")
Expand All @@ -246,7 +245,6 @@ psRace <- function(iraceResults, max_experiments, conf_ids = NULL, iteration_eli
iraceResults$experiments <- merge_matrix(iraceResults$experiments, raceResults$experiments)
iraceResults$iterationElites[indexIteration] <- elite_configurations[[".ID."]][1L]
iraceResults$allElites[[indexIteration]] <- elite_configurations[[".ID."]]
race_state$elite_configurations <- elite_configurations
iraceResults$scenario <- scenario
iraceResults$state <- race_state
# FIXME: This log should contain only information of what was done in the
Expand Down
84 changes: 49 additions & 35 deletions R/race-wrapper.R
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ target_error <- function(err_msg, output, scenario, target_runner_call,
"\n", .irace_msg_prefix, advice_txt)
}

check_output_target_evaluator <- function (output, scenario, target_runner_call = NULL, bound = NULL)
check_output_target_evaluator <- function (output, scenario, target_runner_time,
target_runner_call, bound)
{
if (!is.list(output)) {
output <- list()
Expand All @@ -104,15 +105,21 @@ check_output_target_evaluator <- function (output, scenario, target_runner_call
} else if (is_na_nowarn(output$cost)) {
err_msg <- "The output of targetEvaluator is not numeric!"
}
if (scenario$batchmode != 0 && scenario$maxTime > 0) {
if (is.null (output$time)) {
err_msg <- "When batchmode != 0 and maxTime > 0, the output of targetEvaluator must be two numbers 'cost time'!"
if (scenario$maxTime > 0 || scenario$capping) {
if (scenario$batchmode != 0) {
if (is.null (output$time))
err_msg <- "When batchmode != 0 and maxTime > 0, the output of targetEvaluator must be two numbers 'cost time'!"
# With scenario$capping == TRUE, we may have pre-executed targetRunner
# (which_elite_exe) that already have recorded the time, so when we
# reach this point, we may not have 'time'.
} else if (!scenario$capping && is.null(target_runner_time) && is.null(output$time)) {
err_msg <- "Either targetRunner or targetEvaluator must return 'time' !"
}
}
if (is.null(output$time)) {
output$time <- NA_real_
} else {
if (is_na_nowarn(output$time)) {
if (!is.null(output$time)) {
if (!is.null(target_runner_time)) {
err_msg <- "Both targetRunner and targetEvaluator cannot return 'time' !"
} else if (is_na_nowarn(output$time)) {
err_msg <- "The time returned by targetEvaluator is not numeric!"
} else if (is.infinite(output$time)) {
err_msg <- "The time returned by targetEvaluator is not finite!"
Expand All @@ -125,13 +132,17 @@ check_output_target_evaluator <- function (output, scenario, target_runner_call
err_msg <- paste0("The time returned by targetEvaluator (", output$time, ") does not respect the given bound of ", bound, "!")
}
}
} else {
output$time <- target_runner_time
}
}

if (!is.null(err_msg)) {
if (is.null(err_msg)) {
output$error <- NULL
} else {
target_error (err_msg, output, scenario,
target_runner_call = target_runner_call,
target_evaluator_call = output$call)
target_runner_call = target_runner_call,
target_evaluator_call = output$call)
}
output
}
Expand Down Expand Up @@ -239,27 +250,25 @@ check_output_target_runner <- function(output, scenario, bound = NULL)

err_msg <- output$error
if (is.null(err_msg)) {
if (!is.null (output$cost)) {
if (is_na_or_empty(output$cost)) {
err_msg <- "The cost returned by targetRunner is not numeric!"
}
if (is.null(output$cost)) {
output$cost <- NULL # make sure to delete it.
} else if (is_na_or_empty(output$cost)) {
err_msg <- "The cost returned by targetRunner is not numeric!"
}

if (is.null(output$time)) {
output$time <- NA_real_
output$time <- NULL # make sure to delete it.
} else if (is.na(output$time)) {
err_msg <- paste0("The time returned by targetRunner is not numeric!")
} else if (is.infinite(output$time)) {
err_msg <- paste0("The time returned by targetRunner is not finite!")
} else if (output$time <= 0) {
err_msg <- paste0("The value of time (", output$time, ") returned by targetRunner must be strictly positive!")
} else {
if (is.na(output$time)) {
err_msg <- paste0("The time returned by targetRunner is not numeric!")
} else if (is.infinite(output$time)) {
err_msg <- paste0("The time returned by targetRunner is not finite!")
} else if (output$time <= 0) {
err_msg <- paste0("The value of time (", output$time, ") returned by targetRunner must be strictly positive!")
} else {
# Fix time.
output$time <- max(output$time, scenario$minMeasurableTime)
if (!is.null(bound) && !is.na(bound) && bound > 0 && bound + scenario$minMeasurableTime < output$time) {
err_msg <- paste0("The time returned by targetRunner (", output$time, ") does not respect the given bound of ", bound, "!")
}
# Fix time.
output$time <- max(output$time, scenario$minMeasurableTime)
if (!is.null(bound) && !is.na(bound) && bound > 0 && bound + scenario$minMeasurableTime < output$time) {
err_msg <- paste0("The time returned by targetRunner (", output$time, ") does not respect the given bound of ", bound, "!")
}
}
if (is.null(err_msg)) {
Expand All @@ -268,23 +277,25 @@ check_output_target_runner <- function(output, scenario, bound = NULL)
# unless using batchmode, in that case targetRunner returns neither the
# time nor the cost.
if (scenario$batchmode != 0) {
if (!is.na(output$time) || !is.null(output$cost)) {
if (!is.null(output$time) || !is.null(output$cost)) {
err_msg <- "When batchmode != 0, the output of targetRunner must not contain a cost nor a time!"
}
} else if (scenario$maxTime > 0 && is.na(output$time)) {
} else if (scenario$maxTime > 0 && is.null(output$time)) {
err_msg <- "The output of targetRunner must be one number 'time'!"
} else if (!is.null(output$cost)) {
err_msg <- "The output of targetRunner must be empty or just one number 'time'!"
}
} else if (scenario$maxTime > 0 && (is.null(output$cost) || is.na(output$time))) {
} else if (scenario$maxTime > 0 && (is.null(output$cost) || is.null(output$time))) {
err_msg <- "The output of targetRunner must be two numbers 'cost time'!"
} else if (scenario$maxExperiments > 0 && is.null(output$cost)) {
err_msg <- "The output of targetRunner must be one number 'cost'!"
}
}
}

if (!is.null(err_msg)) {
if (is.null(err_msg)) {
output$error <- NULL
} else {
target_error (err_msg, output, scenario, target_runner_call = output$call)
}
output
Expand Down Expand Up @@ -602,6 +613,8 @@ execute_evaluator <- function(target_evaluator, experiments, scenario, target_ou
## FIXME: We do not need the configurations_id argument:
irace.assert(isTRUE(all.equal(configurations_id,
unique(sapply(experiments, getElement, "id_configuration")))))
configurations_id <- unique(unlist(lapply(experiments, getElement, "id_configuration"),
recursive = FALSE, use.names = FALSE))
nconfs <- length(configurations_id)
# Evaluate configurations sequentially.
for (k in seq_along(experiments)) {
Expand All @@ -610,12 +623,13 @@ execute_evaluator <- function(target_evaluator, experiments, scenario, target_ou
output <- target_evaluator(experiment = experiment, num_configurations = nconfs,
all_conf_id = configurations_id, scenario = scenario,
target_runner_call = target_runner_call)
output <- check_output_target_evaluator(output, scenario, target_runner_call = target_runner_call, bound = experiment$bound)
output <- check_output_target_evaluator(output, scenario, target_runner_time = target_output[[k]]$time,
target_runner_call = target_runner_call, bound = experiment$bound)
target_output[[k]]$cost <- output$cost
# targetEvaluator may return time, for example for batchmode != 0.
target_output[[k]]$time <- output$time
if (is.null(target_output[[k]]$call))
target_output[[k]]$call <- output$call
if (is.null(target_output[[k]]$time) || !is.null.or.na(output$time))
target_output[[k]]$time <- output$time
}
target_output
}
Loading

0 comments on commit a2bb7d8

Please sign in to comment.