Skip to content

Roxygen R6 Guide

M. Böcker edited this page Jan 20, 2020 · 4 revisions

We will probably change our documentation to roxygen2 as it supports R6 now.

Transition

The old documentation style and the new R6 style aren't too dissimilar. To convert any old documentation to the new style, you want to work top-to-bottom. Start with the class title and description and follow this example:

#' @title Abstract Terminator Class
#'
#' @usage NULL
#' @format [R6::R6Class] object.
#' @include mlr_terminators.R
#'
#' @description
#' Abstract `Terminator` class that implements the base functionality each terminator must provide.
#' A terminator is an object that determines when to stop the tuning.
#'

The old style already contains all the information needed to document it with the new style. Simply remove the tags and you're done! The first line is automatically the class title and any following line thats not in another section will be the description. Make sure to remove the @usage and @format tags since they are no longer needed. Move any includes down to the end of the first Roxygen block to avoid it being recognized as the description.

#' Abstract Terminator Class
#'
#' Abstract `Terminator` class that implements the base functionality each terminator must provide.
#' A terminator is an object that determines when to stop the tuning.

Below that in the file will be documentation for the constructor, fields and methods.

#' @section Construction:
#' ```
#' t = Terminator$new(param_set = ParamSet$new())
#' ```
#' * `param_set` :: [paradox::ParamSet]\cr
#'   Set of control parameters for terminator.
#'
#' @section Fields:
#'
#' * `param_set` :: [paradox::ParamSet]; from construction.
#'
#' @section Methods:
#' * `is_terminated(instance)`\cr
#'   [TuningInstance] -> `logical(1)`\cr
#'   Is `TRUE` iff the termination criterion is positive, and `FALSE` otherwise.
#'   Must be implemented in each subclass.

Make sure to move these to the correct place in the file (before the constructor, field, method, respectively). Documentation for fields and active bindings will need to use the @field tag whereas the constructor and methods will need to document all of their parameters and the return value. Make sure to include the expected type of the value by using this format:

#' @param <name> <type> :: <description>

Afterwards your class documentation should look like this:

Terminator = R6Class("Terminator",
  public = list(
    #' @field param_set `param_set` :: [paradox::ParamSet]; from construction.
    param_set = NULL,

    #' @param param_set [paradox::ParamSet] :: Set of control parameters for terminator.
    initialize = function(param_set = ParamSet$new()) {
      self$param_set = assert_param_set(param_set)
    },

    format = function() {
      sprintf("<%s>", class(self)[1L])
    },

    print = function() {
      catf(self$format())
      catf(str_indent("* Parameters:", as_short_string(self$param_set$values)))
    },

    #' Is `TRUE` iff the termination criterion is positive, and `FALSE` otherwise.
    #' Must be implemented in each subclass.
    #' @param instance [TuningInstance]
    #' @return logical
    is_terminated = function(instance) TRUE # overwrite in subclasses
  )
)

Leave the @family and @export tags as they were.

#' @family Terminator
#' @export

In the end, your class should look a little something like this (summary):

#' Abstract Terminator Class
#'
#' Abstract `Terminator` class that implements the base functionality each terminator must provide.
#' A terminator is an object that determines when to stop the tuning.
#'
#' Termination of tuning works as follows:
#' * Evaluations in a tuner are performed in batches.
#' * Before and after each batch evaluation, the [Terminator] is checked, and if it is positive, we stop.
#' * The tuning algorithm itself might decide not to produce any more points, or even might decide to do a smaller batch in its last evaluation.
#'
#' Therefore the following note seems in order:
#' While it is definitely possible to execute a fine-grained control for termination, and for many tuners we can specify exactly when to stop,
#' it might happen that too few or even too many evaluations are performed, especially if multiple points are evaluated in a single batch (c.f. batch size parameter of many tuners).
#' So it is advised to check the size of the returned archive, in particular if you are benchmarking multiple tuners.
#'
#' @include mlr_terminators.R
#' @family Terminator
#' @export
Terminator = R6Class("Terminator",
  public = list(
    #' @field param_set [paradox::ParamSet] :: From construction.
    param_set = NULL,

    #' @param param_set [paradox::ParamSet] :: Set of control parameters for terminator.
    initialize = function(param_set = ParamSet$new()) {
      self$param_set = assert_param_set(param_set)
    },

    format = function() {
      sprintf("<%s>", class(self)[1L])
    },

    print = function() {
      catf(self$format())
      catf(str_indent("* Parameters:", as_short_string(self$param_set$values)))
    },

    #' Is `TRUE` iff the termination criterion is positive, and `FALSE` otherwise.
    #' Must be implemented in each subclass.
    #' @param instance [TuningInstance]
    #' @return logical
    is_terminated = function(instance) TRUE # overwrite in subclasses
  )
)
Clone this wiki locally