DirtStats
DirtStats

Reputation: 599

How do I pass constant parameters through an optimization function that calls another function in R?

I am trying to minimize a function that is conceptually similar to this:

minim<-function(a,b,state){
if(state=="TRUE"){out<-2*a^2+b}else{out<-2*a^3-b}
return(out) }

And I am calling GenSA like this (I wish to optimize on a and b only and not optimize state):

upper_limits<-c(10,10)
lower_limits<-c(-10,-10)
params<-c(1,1)

minim<-function(a,b,state){
  if(state=="TRUE"){out<-2*a^2+b}else{out<-2*a^3-b}
  return(out)
  }

minim_state_TRUE_fit<-GenSA(par=params,function(params) minim(params[1],params[2]), 
                      lower=lower_limits, upper=upper_limits, 
                      control=list(max.time=100),state="TRUE")

And the error I get is:

Error in fn(par, ...) : unused argument (state = "TRUE")

GenSA is supposed to be able to accept additional arguments that it will pass to the function being called. It appears that state="TRUE" is not being passed to minim for some reason. Am I coding this incorrectly? I have not been able to find an example of GenSA use where an additional argument is used to check my R grammar.

Upvotes: 1

Views: 1061

Answers (2)

IRTFM
IRTFM

Reputation: 263362

If you want to pass named arguments in to a function you need to provide formal arguments to accept them, so put in "dots" in for the fn argument definition and the minim call:

minim_state_TRUE_fit<-GenSA(par=params,fn=function(params, ...) {     
                                                minim(params[1],params[2], ...) }, 
                            lower=lower_limits, upper=upper_limits, 
                            control=list(max.time=100), state="TRUE")

Upvotes: 1

Vandenman
Vandenman

Reputation: 3176

You are optimizing the function function(params) minim(params[1],params[2]). This function does not contain the argument state. You can fix this like this:

minim <- function(a, b, state) {
  if (state) {
    out <- 2 * a^2 + b
  } else {
    out<-2 * a^3 - b
  }
  return(out)
}

fn = function(params, state) minim(params[1],params[2], state)

minim_state_TRUE_fit<-GenSA(par=params,fn = fn, 
                            lower=lower_limits, upper=upper_limits, 
                            control=list(max.time=100), state = TRUE)

Also note that I changed state = "TRUE" to state = TRUE. If you're using it for a logical test it's better to change it into a logical if possible.

Upvotes: 2

Related Questions