Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I pass more arguments to optimize() function in R

Tags:

optimization

r

The optimize function is only designed to handle one function argument as I understand it. But sometimes a function can depend on different input ranges of variables and parameters.

for example:

x.r<-rnorm(100)
y<-function(x,p) -x^2+p*1/exp(x^3)
optimize(y,upper=range(x.r)[2],lower=range(x.r)[1])

x.r. the domain of x being passed to y can change from sample to sample. Instead of using a generic x, I want to be able to draw from many x.r domains of values to run y over. Is there some way to modify the optimize function so that I could pass both y, the function, and x it's domain variables as well as the optimize parameter(s) p?

With the above I get an error:

> optimize(y,upper=range(x.r)[2],lower=range(x.r)[1])
Error in p * 1 : 'p' is missing

edit: per suggestion below (which makes sense... but) I tried.

x.r<-rnorm(100)
p<-seq(-5,5,1)
y<-function(x,p) -x^2+p*1/exp(x^3)
optimize(y,upper=range(x.r)[2],lower=range(x.r)[1],p)

results was: Error in p * 1 : 'p' is missing

Also,

> optimize(y,upper=range(x.r)[2],lower=range(x.r)[1],p,x.r)
Error in optimize(y, upper = range(x.r)[2], lower = range(x.r)[1], p,  : 
  invalid function value in 'optimize'

any other ideas?

edit 2: per comments below a loop would work, but seems like an odd way to approach it. I'm not sure if it's uniquely taking the x.r domain into account either.

x.r<-rnorm(100)
p<-seq(-5,5,1)
y<-function(p=p,x=x.r) -x^2+p*1/exp(x^3)
for(v in p){
print(optimize(y,upper=range(p)[2],lower=range(p)[1],p=v))}

> for(v in p){
+ print(optimize(y,upper=range(p)[2],lower=range(p)[1],p=v))}
$minimum
[1] -4.999944

$objective
[1] -9.637547e+54

$minimum
[1] -4.999944

$objective
...
like image 664
pat Avatar asked Oct 06 '22 00:10

pat


2 Answers

I call optimise over p

x.r <- rnorm(100)
p   <- seq(-5,5,1)
y<-function(x,p) -x^2+ p/exp(x^3)
ll <- lapply(p,function(i)
         optimize(y,upper=range(x.r)[2],lower=range(x.r)[1],p=i))

ll[[which.min(sapply(ll,'[[','minimum'))]]

$minimum
[1] -2.14628

$objective
[1] -98357.67

Of course if maximum = TRUE the last becomes

ll[[which.max(sapply(ll,'[[','maximum'))]]
like image 68
agstudy Avatar answered Oct 20 '22 04:10

agstudy


Another way out of this which works even when the thing you are calling doesn't allow you to specify extra named parameters that are passed on to the function is to create a function-generating function that generates a function with a given p.

yp <- function(p){force(p);function(x){-x^2+p*1/exp(x^3)}}
yp1=yp(1)
yp2=yp(2)

and now the yp functions are just a function of x:

> yp1(0)
[1] 1
> yp2(0)
[1] 2

so your loop becomes:

x.r <- rnorm(100)
pv   <- seq(-5,5,1)

ll <- lapply(pv,function(p){
        Y = yp(p)
        optimize(Y,upper=range(x.r)[2],lower=range(x.r)[1])
        })

which is looping over the pv vector and putting each value in p to create a function Y based on that value. Nothing else (apart from upper and lower) is passed into optimize.

like image 28
Spacedman Avatar answered Oct 20 '22 03:10

Spacedman