Wednesday, December 26, 2012

Wrapper functions in GNU R

Recently I have been working with GNU R optimization routines a lot. Function optim has a nice trace option that allows to monitor optimization progress. Another standard function optimize has no such feature but it is possible to add outside tracking to it.

Let us start with an example from documentation:

f <- function (x, a) { (x - a) ^ 2 }
print(optimize(f, c(0, 1), tol = 0.0001, a = 1/3))

which produces:

$minimum
[1] 0.3333333

$objective
[1] 0

We only get the final result of the optimization. The simple way to add tracing is by inserting print statement inside optimized function like this:

f <- function (x, a) {
    print(x)
    (x - a) ^ 2
}
print(optimize(f, c(0, 1), tol = 0.0001, a = 1/3))

The call produces the following output:

[1] 0.381966
[1] 0.618034
[1] 0.236068
[1] 0.3333333
[1] 0.3333
[1] 0.3333667
[1] 0.3333333
$minimum
[1] 0.3333333

$objective
[1] 0

However, GNU R allows for a much fancier method that at the same time shows some nice features of the language itself. We use original function but add a wrapper around it:

wrap.f <- function(f, minimum = TRUE) {
    calls <- NULL
    return(list(f = function(x, ...) {
                    calls <<- c(calls, x)
                    ifelse(minimum,f(x, ...), -f(x, ...))
                },
                getter = function() { return(calls) },
                reset = function() { calls <<- NULL }))
}
wf <- wrap.f(function (x, a) { (x - a) ^ 2 })
print(optimize(wf$f, c(0, 1), tol = 0.0001, a = 1/3))
print(wf$getter())
wf$reset()
print(wf$getter())

The wrap.f function allows for tracking of calls of its first argument and to change optimization direction (this is possible through optimize function, but I add this as an example what can be achieved using this method). It holds internal variable calls which keeps track of calls to f function. It can be accessed using getter function and reset using reset function. The last three lines of code present the effect of resetting calls variable. Here is the output from the code:

$objective
[1] 0

[1] 0.3819660 0.6180340 0.2360680 0.3333333 0.3333000 0.3333667 0.3333333
NULL

The wrapping method presented here can be used as a replacement for S4 classes in simple situations. We use the environment created by wrap.f function to store attributes and return methods that can access and modify them.

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.